﻿
Option Explicit On
'*******************************************************************
' Program: pkgVisio
' Author: Albert E Edlund
' Date:
'
' Purpose:
' Working with office object XML
'
'*******************************************************************

#Region " imports "

Imports System
Imports System.Object
Imports System.IO
Imports System.IO.TextReader
' need to reference windowsbase in .net
Imports System.IO.Packaging

' need for dbconnectionstringbuilder used in clsConnections
Imports System.Data.Common

Imports System.Windows
Imports System.Windows.Forms
Imports System.Text.StringBuilder

Imports Microsoft.VisualBasic

Imports System.Text
Imports System.Collections
Imports System.Collections.Generic
Imports System.Collections.ObjectModel

Imports System.Xml
Imports System.Linq
Imports System.Linq.Enumerable
Imports System.Windows.Input

Imports System.Xml.Serialization
Imports System.Xml.Linq
Imports System.Xml.XPath

Imports ADODB
Imports System.Data
Imports System.Data.OleDb
Imports System.Data.Sql


Imports Microsoft.Practices.EnterpriseLibrary.Common
Imports Microsoft.Practices.EnterpriseLibrary.ExceptionHandling
Imports Microsoft.Practices.EnterpriseLibrary.ExceptionHandling.Logging



' visio v15 does not use a xName prefix which may put it into conflict with other open office apps
Imports <xmlns="http://schemas.microsoft.com/office/visio/2012/main">
Imports <xmlns:rs="urn:schemas-microsoft-com:rowset">

' generic namespace for office open xml, used in all of them
Imports <xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships">

Imports pkgVisio.clsVisPackage
Imports pkgVisio.clsStructures

#End Region



'**********************************************************************************
'
'**********************************************************************************
'
Public Class clsShape


#Region " Properties and Declarations "

    '
    '
    '
    Public Enum ivShapeTypes
        visTypeInval = 0
        visTypeGroup = 2
        visTypeShape = 3
        visTypeForeignObject = 4
        visTypeGuide = 5
        visTypeDoc = 6
        visTypeMetafile = 16
        visTypeBitmap = 32
    End Enum


    '
    '
    '
    Public m_visPackage As clsVisPackage
    Public Property visPackage As clsVisPackage
        Get
            visPackage = Me.m_visPackage
        End Get
        Set(value As clsVisPackage)
            If (value Is Nothing) Then
                Throw New System.ArgumentNullException("Value", _
                    "visPackage is Null.")
            End If
            Me.m_visPackage = value
        End Set
    End Property


    '
    '
    '
    Private m_Cell As clsCell
    Public Property _Cell As clsCell
        Get
            _Cell = m_Cell
        End Get
        Set(value As clsCell)
            m_Cell = value
        End Set
    End Property

    '
    '
    '
    Private _strShpName As String
    Public Property strShpName As String
        Get
            strShpName = _strShpName
        End Get
        Set(value As String)
            _strShpName = value
        End Set
    End Property

    '
    '
    '
    Private _strShpNameU As String
    Public Property strShpNameU As String
        Get
            strShpNameU = _strShpNameU
        End Get
        Set(value As String)
            _strShpNameU = value
        End Set
    End Property

    '
    '
    '
    Private _lngShpId As Long
    Public Property lngShpId As Long
        Get
            lngShpId = _lngShpId
        End Get
        Set(value As Long)
            _lngShpId = value
        End Set
    End Property

    '
    '
    '
    Private _strShpType As String
    Public Property strShpType As String
        Get
            strShpType = _strShpType
        End Get
        Set(value As String)
            _strShpType = value
        End Set
    End Property

    '
    '
    '
    Private _lngShpMaster As Long
    Public Property lngShpMaster As Long
        Get
            lngShpMaster = _lngShpMaster
        End Get
        Set(value As Long)
            _lngShpMaster = value
        End Set
    End Property


    '
    '
    '
    Public _xDoc As XDocument
    Public Property xDoc As XDocument
        Get
            If Me._xDoc Is Nothing Then
                Me._xDoc = New XDocument
            End If
            ' visual studio get's confused and changes the namespaces
            Dim strEmptyNS As String = " xmlns="""""
            If Me._xDoc IsNot Nothing Then
                Dim strReplace As String = Me._xDoc.ToString
                strReplace = strReplace.Replace(strEmptyNS, " ")
                Me._xDoc = XDocument.Parse(strReplace)
            End If
            xDoc = Me._xDoc
        End Get
        Set(value As XDocument)
            Me._xDoc = value
        End Set
    End Property


    '
    '
    '
    Private _ShpSource As XElement
    Public Property ShpSource As XElement
        Get
            ShpSource = _ShpSource
        End Get
        Set(value As XElement)
            _ShpSource = value
        End Set
    End Property

    '
    '
    '
    Private _dictSections As Dictionary(Of String, XElement)
    Public Property dictSections As Dictionary(Of String, XElement)
        Get
            dictSections = _dictSections
        End Get
        Set(value As Dictionary(Of String, XElement))
            _dictSections = value
        End Set
    End Property

    '
    '
    '
    Private _dictCells As Dictionary(Of String, XElement)
    Public Property dictCells As Dictionary(Of String, XElement)
        Get
            dictCells = _dictCells
        End Get
        Set(value As Dictionary(Of String, XElement))
            _dictCells = value
        End Set
    End Property

    '
    '
    '
    Private _dictRowAttCells As Dictionary(Of String, String)
    Public Property dictRowAttCells As Dictionary(Of String, String)
        Get
            dictRowAttCells = Me._dictRowAttCells
        End Get
        Set(value As Dictionary(Of String, String))
            Me._dictRowAttCells = value
        End Set
    End Property

    '
    '
    '
    Private _dictRowElemCells As Dictionary(Of String, String)
    Public Property dictRowElemCells As Dictionary(Of String, String)
        Get
            dictRowElemCells = Me._dictRowElemCells
        End Get
        Set(value As Dictionary(Of String, String))
            Me._dictRowElemCells = value
        End Set
    End Property

    '
    '
    '
    Private _dataTable As System.Data.DataTable
    Public Property dataTable As System.Data.DataTable
        Get
            dataTable = Me._dataTable
        End Get
        Set(value As System.Data.DataTable)
            Me._dataTable = value
        End Set
    End Property


#End Region


#Region " test strings "

    '
    ' the simple shape is a rectangle with fielddata (moves the shapename to the text)
    '
    Public Const strSimpleShape = "<Shape ID=""1"" Type=""Shape"" LineStyle=""3"" FillStyle=""3"" TextStyle=""3"">" _
        & "<Cell N=""PinX"" V=""0"" />" _
        & "<Cell N=""PinY"" V=""0"" />" _
        & "<Cell N=""Width"" V=""0.5"" />" _
        & "<Cell N=""Height"" V=""0.5"" />" _
        & "<Cell N=""LocPinX"" V=""0.25"" F=""Width*0.5"" />" _
        & "<Cell N=""LocPinY"" V=""0.25"" F=""Height*0.5"" />" _
        & "<Cell N=""Angle"" V=""0"" />" _
        & "<Cell N=""FlipX"" V=""0"" />" _
        & "<Cell N=""FlipY"" V=""0"" />" _
        & "<Cell N=""ResizeMode"" V=""0"" />" _
        & "<Cell N=""LayerMember"" V="""" />" _
        & "<Section N=""Character"">" _
        & "<Row IX=""0"">" _
        & "<Cell N=""Size"" V=""0.1388888888888889"" U=""PT""/>" _
        & "</Row>" _
        & "</Section>" _
        & "<Section N=""Field"">" _
        & "<Row IX=""0"">" _
        & "<Cell N=""Value"" V=""ShapeA"" U=""STR"" F=""NAME()""/>" _
        & "<Cell N=""Format"" V=""@"" U=""STR"" F=""FIELDPICTURE(37)""/>" _
        & "<Cell N=""Type"" V=""0""/>" _
        & "<Cell N=""Calendar"" V=""0""/>" _
        & "<Cell N=""ObjectKind"" V=""0""/>" _
        & "</Row>" _
        & "</Section>" _
        & "<Text>" _
        & "<fld IX=""0"">ShapeA</fld>" _
        & "</Text>" _
        & "<Section N=""Geometry"" IX=""0"">" _
        & "<Cell N=""NoFill"" V=""0""/>" _
        & "<Cell N=""NoLine"" V=""0""/>" _
        & "<Cell N=""NoShow"" V=""0""/>" _
        & "<Cell N=""NoSnap"" V=""0""/>" _
        & "<Cell N=""NoQuickDrag"" V=""0""/> " _
        & "<Row T=""RelMoveTo"" IX=""1"">" _
        & "<Cell N=""X"" V=""0""/>" _
        & "<Cell N=""Y"" V=""0""/>" _
        & "</Row>" _
        & "<Row T=""RelLineTo"" IX=""2"">" _
        & "<Cell N=""X"" V=""1""/>" _
        & "<Cell N=""Y"" V=""0""/>" _
        & "</Row>" _
        & "<Row T=""RelLineTo"" IX=""3"">" _
        & "<Cell N=""X"" V=""1""/>" _
        & "<Cell N=""Y"" V=""1""/>" _
        & "</Row>" _
        & "<Row T=""RelLineTo"" IX=""4"">" _
        & "<Cell N=""X"" V=""0""/>" _
        & "<Cell N=""Y"" V=""1""/>" _
        & "</Row>" _
        & "<Row T=""RelLineTo"" IX=""5"">" _
        & "<Cell N=""X"" V=""0""/>" _
        & "<Cell N=""Y"" V=""0""/>" _
        & "</Row>" _
        & "</Section>" _
        & "</Shape>"

    '
    ' the simple connector is a dynamic connector configured to use name connection points
    ' since we will change the name add the attribute
    '
    Public Const strSimpleConnector As String = _
        "<Shape ID=""1"" NameU=""Dynamic connector"" Name=""Dynamic connector"" Type=""Shape"" Master=""2""> " _
        & "<Cell N=""PinX"" V=""4"" U=""IN"" F=""Inh"" />" _
        & "<Cell N=""PinY"" V=""5.5"" U=""IN"" F=""Inh"" />" _
        & "<Cell N=""Width"" V=""1.25"" F=""GUARD(EndX-BeginX)"" />" _
        & "<Cell N=""Height"" V=""0.25"" F=""GUARD(EndY-BeginY)"" />" _
        & "<Cell N=""LocPinX"" V=""0.625"" F=""Inh"" />" _
        & "<Cell N=""LocPinY"" V=""0.125"" F=""Inh"" />" _
        & "<Cell N=""LayerMember"" V="""" />" _
        & "<Cell N=""ShapeRouteStyle"" V=""2"" />" _
        & "<Cell N=""ConLineRouteExt"" V=""1"" /> " _
        & "<Cell N=""BeginX"" F=""GUARD(PAR(PNT(ShapeA!Connections.Right.X,ShapeA!Connections.Right.Y)))"" />" _
        & "<Cell N=""BeginY"" F=""GUARD(PAR(PNT(ShapeA!Connections.Right.X,ShapeA!Connections.Right.Y)))"" />" _
        & "<Cell N=""EndX"" F=""GUARD(PAR(PNT(ShapeB!Connections.Left.X,ShapeB!Connections.Left.Y)))"" />" _
        & "<Cell N=""EndY"" F=""GUARD(PAR(PNT(ShapeB!Connections.Left.X,ShapeB!Connections.Left.Y)))"" />" _
        & "<Cell N=""BegTrigger"" V=""1"" F=""_XFTRIGGER(Dynamic connector!EventXFMod)"" />" _
        & "<Cell N=""EndTrigger"" V=""1"" F=""_XFTRIGGER(Dynamic connector!EventXFMod)"" />" _
        & "<Cell N=""TxtPinX"" V=""0.75"" F=""Inh"" />" _
        & "<Cell N=""TxtPinY"" V=""0"" F=""Inh"" />" _
        & "<Section N=""Control"">" _
        & "<Row N=""TextPosition"">" _
        & "<Cell N=""X"" V=""0.75""/>" _
        & "<Cell N=""Y"" V=""0""/>" _
        & "<Cell N=""XDyn"" V=""0.75"" F=""Inh""/>" _
        & "<Cell N=""YDyn"" V=""0"" F=""Inh""/>" _
        & "</Row>" _
        & "</Section>" _
        & "<Section N=""Geometry"" IX=""0"">" _
        & "<Cell N=""NoFill"" V=""1"" />" _
        & "<Cell N=""NoLine"" V=""0"" />" _
        & "<Cell N=""NoShow"" V=""0"" />" _
        & "<Cell N=""NoSnap"" V=""0"" />" _
        & "<Cell N=""NoQuickDrag"" V=""0"" />" _
        & "<Row T=""MoveTo"" IX=""1"">" _
        & "<Cell N=""Y"" V=""0.125"" /> " _
        & "</Row>" _
        & "<Row T=""LineTo"" IX=""2"">" _
        & "<Cell N=""X"" V=""1""/>" _
        & "<Cell N=""Y"" V=""0.125""/>" _
        & "</Row>" _
        & "<Row T=""LineTo"" IX=""3"" Del=""1"" />" _
        & "</Section>" _
        & "</Shape>"






#End Region

#Region " methods "

    '
    ' populate the dictCells and dictSections for the supplied shape xelement object
    '
    Public Sub getShapeElements()

        If _Cell Is Nothing Then
            _Cell = New clsCell
        End If

        ' make sure the section dictionary exists
        If _dictSections Is Nothing Then
            _dictSections = New Dictionary(Of String, XElement)
        End If
        ' clear the dictionary
        _dictSections.Clear()

        Try

            Dim lngId As Long = -1
            Dim strName As String = "NoShpName"
            Dim strNameU As String = "NoShpNameU"
            Dim strType As String = "NoShpType"
            Dim lngMaster As Long = -1

            ' first the attributes for the shape
            Dim listOfAttributes As IEnumerable(Of XAttribute) = _
                From att In Me.ShpSource.Attributes() _
                Select att

            For Each att As XAttribute In listOfAttributes
                'Debug.Print("Att {0}={1}", att.Name.LocalName, att.Value)
                Select Case LCase(att.Name.LocalName)
                    Case "id"
                        lngId = CLng(att.Value)
                    Case "name"
                        strName = att.Value.ToString
                    Case "nameu"
                        strNameU = att.Value.ToString
                    Case "type"
                        strType = att.Value.ToString
                    Case "master"
                        lngMaster = CLng(att.Value.ToString)
                End Select
            Next att

            lngShpId = lngId
            strShpName = strName
            strShpNameU = strNameU
            strShpType = strType

            ' start the shape drilldown
            Dim listOfElements As IEnumerable(Of XElement) = _
                    From elemData In Me.ShpSource.Elements() _
                    Select elemData

            Dim strCellName As String
            Dim newCell As stcCell = Nothing
            newCell = New stcCell(Nothing, Nothing, Nothing, Nothing)

            For Each elem As XElement In listOfElements
                'Debug.Print("Elem {0} {1}={2}", strShpName, elem.Name.LocalName, elem.Value)
                Select Case LCase(elem.Name.LocalName)

                    Case "cell"
                        newCell.readXElement(elem)
                        strCellName = newCell.cellName
                        ' if section has not been added to the section dictionary, then add it
                        Try
                            If dictCells.ContainsKey(strCellName) = False Then
                                dictCells.Add(strCellName, elem)
                            End If
                        Catch err As System.Collections.Generic.KeyNotFoundException
                        End Try
                    Case "section"
                        getSectionDataFromXElement(elem)
                End Select
            Next elem


        Catch errXml As XmlException
            Dim rethrow As Boolean = ExceptionPolicy.HandleException(errXml, "Log Only Policy")
            If (rethrow) Then
                Throw
            End If
        Catch err As Exception
            Dim rethrow As Boolean = ExceptionPolicy.HandleException(err, "Log Only Policy")
            If (rethrow) Then
                Throw
            End If
        End Try

    End Sub

    '
    ' sections may have attributes and elements, save name and xelement to dictsections
    '
    Private Sub getSectionDataFromXElement(ByVal elemShape As XElement)

        Dim strSectionName As String = ""
        Dim strValue As String = ""
        Dim strFormula As String = ""
        Dim intSectionIndex As Integer = -1


        Try

            ' first the attributes for the shape
            Dim listOfAttributes As IEnumerable(Of XAttribute) = _
                From att In elemShape.Attributes() _
                Select att

            For Each att As XAttribute In listOfAttributes
                'Debug.Print("Att {0}={1}", att.Name.LocalName, att.Value)
                Select Case LCase(att.Name.LocalName)
                    Case "n"
                        strSectionName = att.Value
                    Case "ix"
                        intSectionIndex = CInt(att.Value)
                End Select
            Next att

            ' start the section drilldown
            Dim listOfElements As IEnumerable(Of XElement) = _
                    From elemData In elemShape.Elements() _
                    Select elemData

            For Each elem As XElement In listOfElements
                'Debug.Print("Elem {0} {1}={2}", strShpName, elem.Name.LocalName, elem.Value)
                Select Case LCase(elem.Name.LocalName)
                    Case "row"
                        ' section rows can have attributes (names) and elements (cells)
                        getRowData(elem)
                End Select
            Next elem

            Try
                ' if section has not been added to the section dictionary, then add it
                If dictSections.ContainsKey(strSectionName) = False Then
                    dictSections.Add(strSectionName, elemShape)
                End If
            Catch err As System.Collections.Generic.KeyNotFoundException
            End Try

        Catch errXml As XmlException
            Dim rethrow As Boolean = ExceptionPolicy.HandleException(errXml, "Log Only Policy")
            If (rethrow) Then
                Throw
            End If
        Catch err As Exception
            Dim rethrow As Boolean = ExceptionPolicy.HandleException(err, "Log Only Policy")
            If (rethrow) Then
                Throw
            End If
        End Try

    End Sub

    '
    ' rows may have attributes and elements (cells)
    '
    Private Sub getRowData(ByVal elemRow As XElement)

        Dim strRowName As String = ""
        Dim strRowType As String = ""
        Dim strValue As String = ""
        Dim strFormula As String = ""
        Dim intRowIndex As Integer = -1


        ' first the attributes for the shape
        Dim listOfAttributes As IEnumerable(Of XAttribute) = _
            From att In elemRow.Attributes() _
            Select att

        For Each att As XAttribute In listOfAttributes
            'Debug.Print("Att {0} {1}={2}", strRowName, att.Name.LocalName, att.Value)
            Select Case LCase(att.Name.LocalName)
                Case "n"
                    strRowName = att.Value
                Case "ix"
                    intRowIndex = CInt(att.Value)
                Case "t"
                    strRowType = att.Value
            End Select
        Next att

        ' start the section drilldown
        Dim listOfElements As IEnumerable(Of XElement) = _
                From elemData In elemRow.Elements() _
                Select elemData

        For Each elem As XElement In listOfElements
            'Debug.Print("Elem {0} {1}={2}", strRowName, elem.Name.LocalName, elem.Value)
            Select Case LCase(elem.Name.LocalName)
                Case "cell"
                    Dim newCell As stcCell = Nothing
                    newCell = New stcCell(Nothing, Nothing, Nothing, Nothing)
                    ' section rows can have attributes (names) and elements (cells)
                    newCell.readXElement(elem)
            End Select
        Next elem

    End Sub


    '
    '
    '
    '<xsd:complexType name="IndexedRow_Type">
    '	<xsd:attribute name="IX" type="xsd:unsignedLong"/>
    '	<xsd:attribute name="Del" type="ISOBoolean"/>
    '</xsd:complexType>
    '<xsd:complexType name="NamedRow_Type">
    '	<xsd:attribute name="Name" type="xsd:string"/>
    '	<xsd:attribute name="NameU" type="xsd:string"/>
    '	<xsd:attribute name="Del" type="ISOBoolean"/>
    '	<xsd:attribute name="ID" type="xsd:unsignedLong"/>
    '</xsd:complexType>
    '<xsd:complexType name="NamedIndexedRow_Type">
    '	<xsd:attribute name="Name" type="xsd:string"/>
    '	<xsd:attribute name="NameU" type="xsd:string"/>
    '	<xsd:attribute name="Del" type="ISOBoolean"/>
    '	<xsd:attribute name="ID" type="xsd:unsignedLong"/>
    '	<xsd:attribute name="IX" type="xsd:unsignedLong"/>
    '</xsd:complexType>
    '
    Public Function analyzeSectionRows _
        (ByVal xelemSection As XElement) _
        As System.Data.DataTable


        Me._dictRowAttCells = Nothing
        Me._dictRowAttCells = New Dictionary(Of String, String)
        Me._dictRowElemCells = Nothing
        Me._dictRowElemCells = New Dictionary(Of String, String)


        Me._dataTable = Nothing
        Me._dataTable = New System.Data.DataTable

        Try


            Dim strIX As String = ""
            Dim strTableName As String = ""
            If xelemSection.@IX IsNot Nothing Then
                strIX = xelemSection.@IX.ToString
                strTableName = "section" & "_" & xelemSection.@N.ToString & "_" & strIX
            Else
                strTableName = "section" & "_" & xelemSection.@N.ToString
            End If

            Dim visCell As clsCell = New clsCell


            Dim qryRowInfo = From rowSel In xelemSection...<Row>
            Dim intRowCt As Integer = qryRowInfo.Count


            dictRowAttCells.Clear()
            dictRowElemCells.Clear()

            ' get the cell/field names 
            For Each row In qryRowInfo

                Dim listOfAttributes As IEnumerable(Of XAttribute) = _
                        From att In row.Attributes() _
                        Select att

                For Each att As XAttribute In listOfAttributes
                    Try
                        If dictRowAttCells.ContainsKey(LCase(att.Name.LocalName)) = False Then
                            dictRowAttCells.Add(LCase(att.Name.LocalName), "")
                        End If
                    Catch arg As ArgumentException
                    End Try
                Next att

                ' start the element drilldown
                Dim listOfElements As IEnumerable(Of XElement) = _
                        From elem In row.Elements() _
                        Select elem

                Dim newCell As stcCell = New stcCell(Nothing, Nothing, Nothing, Nothing)
                For Each elem As XElement In listOfElements
                    Dim lngElemCt As Long = listOfElements.LongCount
                    Select Case LCase(elem.Name.LocalName)
                        Case "cell"
                            newCell.readXElement(elem)
                            Try
                                If dictRowElemCells.ContainsKey(LCase(newCell.cellName)) = False Then
                                    dictRowElemCells.Add(LCase(newCell.cellName), "")
                                End If
                                ' check for duplicate names 
                            Catch arg As ArgumentException
                            End Try
                        Case Else
                            MsgBox("RowElement >< Cell = " & elem.Name.LocalName.ToString)
                    End Select
                Next elem
            Next row

            ' how many row_name/type fields
            Dim intAttrTypes As Integer = dictRowAttCells.Count
            ' how many column headings
            Dim intElemTypes As Integer = dictRowElemCells.Count

            ' create the datatable
            If Me._dataTable IsNot Nothing Then
                Me._dataTable = Nothing
            End If
            Me._dataTable = New DataTable
            For Each nameRow In dictRowAttCells
                dataTable.Columns.Add(nameRow.Key.ToString)
            Next nameRow
            For Each cellRow In dictRowElemCells
                dataTable.Columns.Add(cellRow.Key.ToString)
            Next
            dataTable.TableName = strTableName

            ' get the cell/field names 
            For Each row In qryRowInfo

                Dim intDict As Integer
                Dim colAttKeys As System.Collections.Generic.Dictionary(Of String, String).KeyCollection = dictRowAttCells.Keys
                For intDict = 0 To dictRowAttCells.Count - 1
                    Dim strAttrKey As String = colAttKeys(intDict)
                    dictRowAttCells(strAttrKey) = ""
                Next intDict

                Dim colElemKeys As System.Collections.Generic.Dictionary(Of String, String).KeyCollection = dictRowElemCells.Keys
                For intDict = 0 To dictRowElemCells.Count - 1
                    Dim strElemKey As String = colElemKeys(intDict)
                    dictRowElemCells(strElemKey) = ""
                Next

                Dim listOfAttributes As IEnumerable(Of XAttribute) = _
                    From att In row.Attributes() _
                    Select att

                ' update the attributes
                For Each att As XAttribute In listOfAttributes
                    Try
                        If dictRowAttCells.ContainsKey(LCase(att.Name.LocalName)) = True Then
                            If att.Value IsNot Nothing Then
                                dictRowAttCells(LCase(att.Name.LocalName)) = att.Value.ToString
                            Else
                                dictRowAttCells(LCase(att.Name.LocalName)) = "Null String"
                            End If
                        End If
                    Catch arg As ArgumentException
                    End Try
                Next att

                Dim listOfElements As IEnumerable(Of XElement) = _
                        From elem In row.Elements() _
                        Select elem

                Dim stcNewCell As stcCell = New stcCell(Nothing, Nothing, Nothing, Nothing)
                For Each elem As XElement In listOfElements
                    Select Case LCase(elem.Name.LocalName)
                        Case "cell"
                            stcNewCell.readXElement(elem)
                            Try
                                If dictRowElemCells.ContainsKey(LCase(stcNewCell.cellName)) = True Then
                                    dictRowElemCells(LCase(stcNewCell.cellName)) = stcNewCell.cellValue
                                End If
                                ' check for duplicate names 
                            Catch arg As ArgumentException
                            End Try
                    End Select
                Next elem

                Dim newSectionRow As DataRow = Me.dataTable.NewRow
                For Each attRow In dictRowAttCells
                    newSectionRow(attRow.Key.ToString) = attRow.Value.ToString
                Next
                For Each elemRow In dictRowElemCells
                    newSectionRow(elemRow.Key.ToString) = elemRow.Value.ToString
                Next
                Me.dataTable.Rows.Add(newSectionRow)

            Next row


        Catch errXml As XmlException
            Dim rethrow As Boolean = ExceptionPolicy.HandleException(errXml, "Log Only Policy")
            If (rethrow) Then
                Throw
            End If
        Catch err As Exception
            Dim rethrow As Boolean = ExceptionPolicy.HandleException(err, "Log Only Policy")
            If (rethrow) Then
                Throw
            End If
        End Try

        Return Me._dataTable

    End Function


    '
    '
    '
    Public Function existsSection(ByVal strSectName As String) As XElement

        Dim xelemSection As XElement = Nothing

        Dim newXNamespace As XNamespace = Me.visPackage.getNameSpaceFromPrefix(Me.xDoc, "")
        Dim qryProperties = Me.xDoc.Descendants(newXNamespace + "Shape").First

        ' start the shape drilldown
        Dim listOfElements As IEnumerable(Of XElement) = _
                From elemData In qryProperties.Elements() _
                Select elemData

        For Each elem As XElement In listOfElements
            Select Case LCase(elem.Name.LocalName)
                Case "section"
                    If LCase(elem.@N) = LCase(strSectName) Then
                        xelemSection = elem
                        Exit For
                    End If
            End Select
        Next elem


        Return xelemSection

    End Function

    '
    '
    '
    Public Function existsNamedRow _
        (ByVal xelemSection As XElement, _
         ByVal strRowName As String) _
        As Boolean

        Dim blnReturn As Boolean = False

        Try
            ' start the section drilldown
            Dim listOfElements As IEnumerable(Of XElement) = _
                    From elemData In xelemSection.Elements() _
                    Select elemData

            For Each elem As XElement In listOfElements
                'Debug.Print("Elem {0} {1}={2}", strShpName, elem.Name.LocalName, elem.Value)
                Select Case LCase(elem.Name.LocalName)
                    Case "row"
                        ' first the attributes for the shape
                        Dim listOfAttributes As IEnumerable(Of XAttribute) = _
                            From att In elem.Attributes() _
                            Select att

                        For Each att As XAttribute In listOfAttributes
                            'Debug.Print("Att {0} {1}={2}", strRowName, att.Name.LocalName, att.Value)
                            Select Case LCase(att.Name.LocalName)
                                Case "n"
                                    If LCase(att.Value) = LCase(strRowName) Then
                                        blnReturn = True
                                        GoTo ExitHandler
                                    End If
                            End Select
                        Next att
                End Select
            Next elem


        Catch errXml As XmlException
            Dim rethrow As Boolean = ExceptionPolicy.HandleException(errXml, "Log Only Policy")
            If (rethrow) Then
                Throw
            End If
        Catch err As Exception
            Dim rethrow As Boolean = ExceptionPolicy.HandleException(err, "Log Only Policy")
            If (rethrow) Then
                Throw
            End If
        End Try
ExitHandler:
        Return blnReturn

    End Function

    '
    '
    '
    Public Function getNamedRow _
        (ByVal xelemSection As XElement, _
         ByVal strRowName As String) _
        As XElement

        Dim xelemReturn As XElement = Nothing

        Try


            ' start the section drilldown
            Dim listOfElements As IEnumerable(Of XElement) = _
                    From elemData In xelemSection.Elements() _
                    Select elemData

            For Each elem As XElement In listOfElements
                'Debug.Print("Elem {0} {1}={2}", strShpName, elem.Name.LocalName, elem.Value)
                Select Case LCase(elem.Name.LocalName)
                    Case "row"
                        ' first the attributes for the shape
                        Dim listOfAttributes As IEnumerable(Of XAttribute) = _
                            From att In elem.Attributes() _
                            Select att

                        For Each att As XAttribute In listOfAttributes
                            'Debug.Print("Att {0} {1}={2}", strRowName, att.Name.LocalName, att.Value)
                            Select Case LCase(att.Name.LocalName)
                                Case "n"
                                    If LCase(att.Value) = LCase(strRowName) Then
                                        xelemReturn = elem
                                        GoTo ExitHandler
                                    End If
                            End Select
                        Next att
                End Select
            Next elem


        Catch errXml As XmlException
            Dim rethrow As Boolean = ExceptionPolicy.HandleException(errXml, "Log Only Policy")
            If (rethrow) Then
                Throw
            End If
        Catch err As Exception
            Dim rethrow As Boolean = ExceptionPolicy.HandleException(err, "Log Only Policy")
            If (rethrow) Then
                Throw
            End If
        End Try
ExitHandler:
        Return xelemReturn

    End Function


    '
    '
    '
    Public Sub setShapeCell _
        (ByVal strCellName As String, _
         ByVal cellNew As stcCell, _
         Optional ByVal strNewValue As String = Nothing)

        Try


            Dim shpFirst As XElement = Me.xDoc.Elements.FirstOrDefault
            Dim blnFound As Boolean = False

            ' start the shape drilldown
            Dim listOfElements As IEnumerable(Of XElement) = _
                    From elemData In shpFirst.Elements() _
                    Select elemData

            For Each elem As XElement In listOfElements
                'Debug.Print("Elem {0} {1}={2}", strShpName, elem.Name.LocalName, elem.Value)
                Select Case LCase(elem.Name.LocalName)
                    Case "cell"
                        If LCase(elem.@N) = LCase(strCellName) Then
                            blnFound = True
                            Dim xelemNew As XElement = cellNew.writeXelement
                            If strNewValue IsNot Nothing Then
                                xelemNew.SetValue(strNewValue)
                            End If
                            elem.ReplaceWith(xelemNew)
                            Exit For
                        End If
                End Select
            Next elem

            If blnFound = False Then
                shpFirst.Add(cellNew.writeXelement)
            End If

        Catch errXml As XmlException
            Dim rethrow As Boolean = ExceptionPolicy.HandleException(errXml, "Log Only Policy")
            If (rethrow) Then
                Throw
            End If
        Catch err As Exception
            Dim rethrow As Boolean = ExceptionPolicy.HandleException(err, "Log Only Policy")
            If (rethrow) Then
                Throw
            End If
        End Try

    End Sub

    '
    '
    '
    Public Function getXelementCell(ByVal strCellName As String) As stcCell

        Dim cellReturn As stcCell = New stcCell

        Try

            Dim newXNamespace As XNamespace = Me.visPackage.getNameSpaceFromPrefix(Me.xDoc, "")
            Dim qryProperties = Me.xDoc.Descendants(newXNamespace + "Shape").First

            Dim qryCell = From cellSel In qryProperties.<Cell>
                    Where cellSel.@N = strCellName

            If qryCell.Count = 1 Then
                cellReturn.readXElement(qryCell.FirstOrDefault)
            End If

        Catch errXml As XmlException
            Dim rethrow As Boolean = ExceptionPolicy.HandleException(errXml, "Log Only Policy")
            If (rethrow) Then
                Throw
            End If
        Catch err As Exception
            Dim rethrow As Boolean = ExceptionPolicy.HandleException(err, "Log Only Policy")
            If (rethrow) Then
                Throw
            End If
        End Try

        Return cellReturn

    End Function

 

    '
    ' sometimes visual studio decides that a namespace is required, and inserts a blank one.
    ' unfortunately visio can get confused when it finds a blank namespace so we have to remove it.
    '
    Public Sub cleanBlankNameSpace()


        ' visual studio get's confused and changes the namespaces
        Dim strEmptyNS As String = " xmlns="""""
        If Me._xDoc IsNot Nothing Then
            Dim strReplace As String = Me._xDoc.ToString
            strReplace = strReplace.Replace(strEmptyNS, " ")
            Me._xDoc = XDocument.Parse(strReplace)
        End If

    End Sub


#End Region

#Region " Section - Shape Transform "

    Public arrXFormFields() As String = _
    {"Width", "Height", "Angle", "PinX", "PinY", "LocPinX", "LocPinY"}

#End Region

#Region " Section - 1D EndPoints"

    '<Cell N="BeginX" V="2.648148148148148" U="IN" F="PAR(PNT(Town!Connections.Right.X,Town!Connections.Right.Y))" /> 
    '<Cell N="BeginY" V="8.25" U="IN" F="PAR(PNT(Town!Connections.Right.X,Town!Connections.Right.Y))" /> 
    '<Cell N="EndX" V="5.875" U="IN" F="PAR(PNT(Building!Connections.Left.X,Building!Connections.Left.Y))" /> 
    '<Cell N="EndY" V="8.5" U="IN" F="PAR(PNT(Building!Connections.Left.X,Building!Connections.Left.Y))" /> 

    Public arr1DxformFields() As String = _
    {"BeginX", "BeginY", "EndX", "EndY"}

    ' 
    ' pass in two sets of shapes/connectionpoints
    '
    Public Sub update1DEndPointCells _
        (ByVal strFromShape As String, _
         ByVal strFromConnPt As String, _
         ByVal strToShape As String, _
         ByVal strToConnPt As String)

        Try

            Dim strBeginX As String = build1DFormula(strFromShape, strFromConnPt)
            Dim strBeginY As String = build1DFormula(strFromShape, strFromConnPt)
            Dim strEndX As String = build1DFormula(strToShape, strToConnPt)
            Dim strEndY As String = build1DFormula(strToShape, strToConnPt)

            Dim cellBeginX As stcCell = New stcCell("BeginX", Nothing, strBeginX, Nothing)
            Dim cellBeginY As stcCell = New stcCell("BeginY", Nothing, strBeginY, Nothing)
            Dim cellEndX As stcCell = New stcCell("EndX", Nothing, strEndX, Nothing)
            Dim cellEndY As stcCell = New stcCell("EndY", Nothing, strEndY, Nothing)

            setShapeCell("BeginX", cellBeginX)
            setShapeCell("BeginY", cellBeginY)
            setShapeCell("EndX", cellEndX)
            setShapeCell("EndY", cellEndY)



        Catch errXml As XmlException
            Dim rethrow As Boolean = ExceptionPolicy.HandleException(errXml, "Log Only Policy")
            If (rethrow) Then
                Throw
            End If
        Catch err As Exception
            Dim rethrow As Boolean = ExceptionPolicy.HandleException(err, "Log Only Policy")
            If (rethrow) Then
                Throw
            End If
        End Try
    End Sub

    '
    '
    '
    Private Function build1DFormula(ByVal strShape As String, ByVal strConnPt As String) As String

         Return String.Format("PAR(PNT('{0}'!Connections.{1}.X,'{0}'!Connections.{1}.Y))", strShape, strConnPt)

    End Function


#End Region

#Region " Section - Connection Points "

    '<Section N="Connection">
    ' <Row N="Row_1">
    '  <Cell N="X" V="0.75" U="IN" F="Width*0.5" /> 
    '  <Cell N="Y" V="0.75" U="IN" F="Height*0.5" /> 
    '  <Cell N="DirX" V="0" /> 
    '  <Cell N="DirY" V="0" /> 
    '  <Cell N="Type" V="0" /> 
    '  <Cell N="AutoGen" V="0" /> 
    '  <Cell N="Prompt" V="" F="No Formula" /> 
    ' </Row>
    '</Section>

    Public arrConnPtsFields() As String = _
        {"X", "Y", "DirX", "DirY", "Type", "AutoGen", "Prompt"}

    '
    ' our connection point row template
    '
    Private dictConnPtsFields As Dictionary(Of String, String)
    '
    '
    '
    Public Sub initDictConnPtsFields()
        If dictConnPtsFields Is Nothing Then
            dictConnPtsFields = New Dictionary(Of String, String)
        Else
            dictConnPtsFields = Nothing
            dictConnPtsFields = New Dictionary(Of String, String)
        End If
        dictConnPtsFields.Clear()
        Dim visCell As stcCell = New stcCell
        visCell.Reset()
        visCell.cellName = "X"
        visCell.cellValue = "0"
        visCell.cellFormula = "No Formula"
        visCell.cellUnits = "IN"
        dictConnPtsFields.Add("X", visCell.toXML)
        visCell.Reset()
        visCell.cellName = "Y"
        visCell.cellValue = "0"
        visCell.cellFormula = "No Formula"
        visCell.cellUnits = "IN"
        dictConnPtsFields.Add("Y", visCell.toXML)
        visCell.Reset()
        visCell.cellName = "DirX"
        visCell.cellValue = "0"
        dictConnPtsFields.Add("DirX", visCell.toXML)
        visCell.Reset()
        visCell.cellName = "DirY"
        visCell.cellValue = "0"
        dictConnPtsFields.Add("DirY", visCell.toXML)
        visCell.Reset()
        visCell.cellName = "Type"
        visCell.cellValue = "0"
        dictConnPtsFields.Add("Type", visCell.toXML)
        visCell.Reset()
        visCell.cellName = "AutoGen"
        visCell.cellValue = "0"
        dictConnPtsFields.Add("AutoGen", visCell.toXML)
        visCell.Reset()
        visCell.cellName = "Prompt"
        visCell.cellValue = ""
        visCell.cellFormula = "No Formula"
        dictConnPtsFields.Add("Prompt", visCell.toXML)

    End Sub

    '
    '
    '
    Public Function createSectionConnPts() As XElement
        Dim xelemReturn As XElement = New XElement("Section")
        xelemReturn.SetAttributeValue("N", "Connection")
        Return xelemReturn
    End Function

    '
    '
    '
    Public Function createRowConnPts _
        (ByVal strRowName As String, _
         Optional ByVal strIX As String = "01", _
         Optional ByVal blnAddEmpty As Boolean = True, _
         Optional ByVal stcX As stcCell = Nothing, _
         Optional ByVal stcY As stcCell = Nothing, _
         Optional ByVal stcDirX As stcCell = Nothing, _
         Optional ByVal stcDirY As stcCell = Nothing, _
         Optional ByVal stcType As stcCell = Nothing, _
         Optional ByVal stcAutoGen As stcCell = Nothing, _
         Optional ByVal stcPrompt As stcCell = Nothing) _
        As XElement

        Dim xelemReturn As XElement = New XElement("Row")
        Dim cellNew As stcCell = Nothing

        Try

            If dictConnPtsFields Is Nothing _
                Or dictConnPtsFields.Count = 0 Then
                dictConnPtsFields = Nothing
                initDictConnPtsFields()
            End If

            If strIX <> "01" Then
                xelemReturn.SetAttributeValue("IX", strIX)
            End If
            xelemReturn.SetAttributeValue("N", strRowName)
            For Each fldName In dictConnPtsFields
                Select Case LCase(fldName.Key)
                    Case "x"
                        If stcX = Nothing Then
                            If blnAddEmpty = True Then
                                xelemReturn.Add(XElement.Load((XmlReader.Create(New StringReader(fldName.Value)))))
                            End If
                        Else
                            xelemReturn.Add(stcX.writeXelement)
                        End If
                        Exit Select
                    Case "y"
                        If stcY = Nothing Then
                            If blnAddEmpty = True Then
                                xelemReturn.Add(XElement.Load((XmlReader.Create(New StringReader(fldName.Value)))))
                            End If
                        Else
                            xelemReturn.Add(stcY.writeXelement)
                        End If
                        Exit Select
                    Case "dirx"
                        If stcDirX = Nothing Then
                            If blnAddEmpty = True Then
                                xelemReturn.Add(XElement.Load((XmlReader.Create(New StringReader(fldName.Value)))))
                            End If
                        Else
                            xelemReturn.Add(stcDirX.writeXelement)
                        End If
                        Exit Select
                    Case "diry"
                        If stcDirY = Nothing Then
                            If blnAddEmpty = True Then
                                xelemReturn.Add(XElement.Load((XmlReader.Create(New StringReader(fldName.Value)))))
                            End If
                        Else
                            xelemReturn.Add(stcDirY.writeXelement)
                        End If
                        Exit Select
                    Case "autogen"
                        If stcAutoGen = Nothing Then
                            If blnAddEmpty = True Then
                                xelemReturn.Add(XElement.Load((XmlReader.Create(New StringReader(fldName.Value)))))
                            End If
                        Else
                            xelemReturn.Add(stcAutoGen.writeXelement)
                        End If
                        Exit Select
                    Case "prompt"
                        If stcPrompt = Nothing Then
                            If blnAddEmpty = True Then
                                xelemReturn.Add(XElement.Load((XmlReader.Create(New StringReader(fldName.Value)))))
                            End If
                        Else
                            xelemReturn.Add(stcPrompt.writeXelement)
                        End If
                End Select
            Next fldName

        Catch errXml As XmlException
            Dim rethrow As Boolean = ExceptionPolicy.HandleException(errXml, "Log Only Policy")
            If (rethrow) Then
                Throw
            End If
        Catch err As Exception
            Dim rethrow As Boolean = ExceptionPolicy.HandleException(err, "Log Only Policy")
            If (rethrow) Then
                Throw
            End If
        End Try


        Return xelemReturn
    End Function

    '
    '
    '
    Public Function getConnPtRowIndex(ByVal strRowName As String) As Integer

        Dim intReturn As Integer = -1

        Try

            Dim qryDescendants = From descSel In Me.xDoc.Descendants
                                 Select descSel

            Dim xelemSectConn As XElement = Nothing
            For Each xelemShape In qryDescendants
                If LCase(xelemShape.Name.LocalName.ToString) = "section" Then
                    Dim listOfAttributesA As IEnumerable(Of XAttribute) = _
                        From att In xelemShape.Attributes() _
                        Select att
                    For Each att As XAttribute In listOfAttributesA
                        If LCase(att.Name.LocalName) = "n" Then
                            If LCase(xelemShape.@N) = LCase("connection") Then

                                Dim listOfConnElements As IEnumerable(Of XElement) = _
                                        From elem In xelemShape.Elements() _
                                        Select elem

                                If listOfConnElements IsNot Nothing Then
                                    If 0 < listOfConnElements.Count Then
                                        Dim intX As Integer = -1
                                        For intX = 0 To listOfConnElements.Count - 1
                                            Dim xelemRow As XElement = Nothing
                                            xelemRow = listOfConnElements.ElementAt(intX)
                                            If LCase(xelemRow.@N) = LCase(strRowName) Then
                                                intReturn = intX + 100
                                                GoTo ExitHandler
                                            End If
                                        Next intX
                                    End If
                                End If ' test for listofconnelements not nothing 
                            End If
                        End If
                    Next att
                End If
            Next xelemShape




        Catch errXml As XmlException
            Dim rethrow As Boolean = ExceptionPolicy.HandleException(errXml, "Log Only Policy")
            If (rethrow) Then
                Throw
            End If
        Catch err As Exception
            Dim rethrow As Boolean = ExceptionPolicy.HandleException(err, "Log Only Policy")
            If (rethrow) Then
                Throw
            End If
        End Try

ExitHandler:
        Return intreturn

    End Function

    '
    '
    '
    Public Sub AddStandardConnections()

        Try

            Dim xelemSection As XElement = Nothing
            Dim xelemNewSection As XElement = Nothing

            Me.visPackage.readAttAndElem(Me.xDoc, "", "Shape")

            Dim qryShpFirst = From shpSel In Me.xDoc.Descendants
                    Select shpSel
            Dim xelemShpFirst As XElement = qryShpFirst.First
            Dim strName As String = ""
            ' start the element drilldown
            Dim listOfElements As IEnumerable(Of XElement) = _
                    From elem In qryShpFirst.Elements() _
                    Select elem
            If listOfElements IsNot Nothing Then
                If 0 < listOfElements.Count Then
                    For Each elem As XElement In listOfElements


                        strName = elem.Name.LocalName.ToString

                        Select Case LCase(elem.Name.LocalName)
                            Case "section"
                                If LCase(elem.@N) = "connection" Then
                                    xelemSection = elem
                                    Exit For
                                End If
                        End Select
                    Next elem
                End If
            End If

            If xelemSection IsNot Nothing Then
                xelemNewSection = xelemSection
            Else
                xelemSection = createSectionConnPts()
                Me.xDoc.Root.Add(xelemSection)
                xelemNewSection = xelemSection
            End If


                ' visio does not like to mix rows which are indexed (IX=0) and rows that
                ' are named (N="ABC") so we have to remove the indexes and rename the rows
            Dim xelemRow As XElement = Nothing
            Dim intRow As Integer = 0
            Dim strRowName As String = "Row_"
                ' start the section drilldown
            Dim listOfRows As IEnumerable(Of XElement) = _
                    From elemData In xelemNewSection.Elements() _
                    Select elemData
            For Each elem As XElement In listOfRows
                'Debug.Print("Elem {0} {1}={2}", strShpName, elem.Name.LocalName, elem.Value)
                Select Case LCase(elem.Name.LocalName)
                    Case "row"
                        intRow = intRow + 1
                        ' first the attributes for the shape
                        Dim listOfAttributes As IEnumerable(Of XAttribute) = _
                            From att In elem.Attributes() _
                            Select att

                        For Each att As XAttribute In listOfAttributes
                            'Debug.Print("Att {0} {1}={2}", strRowName, att.Name.LocalName, att.Value)
                            Select Case LCase(att.Name.LocalName)
                                Case "n"
                                    ' if named do nothing 
                                Case "ix"
                                    ' if indexed remove the index
                                    att.Remove()
                                    elem.SetAttributeValue("N", strRowName & CStr(intRow))
                                Case "t"
                                    ' if type do nothing
                            End Select
                        Next att
                End Select
            Next elem


                ' visio does not like it if we pass in a wrong value even if we give it a formula
                ' so when we refer to the parent cells we should look up their values
                Dim strWidth As String = Me.visPackage.elemDict("cell_Width")
                Dim dblWidth As Double = CDbl(strWidth.Replace("cellV = ", ""))
                Dim strHeight As String = Me.visPackage.elemDict("cell_Height")
                Dim dblHeight As Double = CDbl(strHeight.Replace("cellV = ", ""))

                Dim newCell As stcCell = New stcCell
                Dim cellX As stcCell = New stcCell("X", CStr(dblWidth * 0.5), "Width * 0.5", "IN")
                Dim cellY As stcCell = New stcCell("Y", CStr(dblHeight * 0.5), "Height * 0.5", "IN")
                Dim cellType As stcCell = New stcCell("Type", "0", "0", "")
                Dim xelemCenter = createRowConnPts("Center", stcX:=cellX, stcY:=cellY, stcType:=cellType)
                xelemNewSection.Add(xelemCenter)

                cellX = Nothing
                cellX = New stcCell("X", "0", "0", "IN")
                cellY = Nothing
                cellY = New stcCell("Y", CStr(dblHeight * 0.5), "Height * 0.5", "IN")
                cellType = Nothing
                cellType = New stcCell("Type", "0", "0", "")
                Dim xelemLeft = createRowConnPts("Left", stcX:=cellX, stcY:=cellY, stcType:=cellType)

                xelemNewSection.Add(xelemLeft)
                cellX = Nothing
                cellX = New stcCell("X", CStr(dblWidth), "Width", "IN")
                cellY = Nothing
                cellY = New stcCell("Y", CStr(dblHeight * 0.5), "Height * 0.5", "IN")
                cellType = Nothing
                cellType = New stcCell("Type", "0", "0", "")
                Dim xelemRight = createRowConnPts("Right", stcX:=cellX, stcY:=cellY, stcType:=cellType)
                xelemNewSection.Add(xelemRight)
                cellX = Nothing
                cellX = New stcCell("X", CStr(dblWidth * 0.5), "Width * 0.5", "IN")
                cellY = Nothing
                cellY = New stcCell("Y", CStr(dblHeight), "Height", "IN")
                cellType = Nothing
                cellType = New stcCell("Type", "0", "0", "")
                Dim xelemTop = createRowConnPts("Top", stcX:=cellX, stcY:=cellY, stcType:=cellType)
                xelemNewSection.Add(xelemTop)

                cellX = Nothing
                cellX = New stcCell("X", CStr(dblWidth * 0.5), "Width * 0.5", "IN")
                cellY = Nothing
                cellY = New stcCell("Y", "0", "0", "IN")
                cellType = Nothing
                cellType = New stcCell("Type", "0", "0", "")
                Dim xelemBottom = createRowConnPts("Bottom", stcX:=cellX, stcY:=cellY, stcType:=cellType)
                xelemNewSection.Add(xelemBottom)

                xelemSection.ReplaceWith(xelemNewSection)

        Catch errXml As XmlException
            Dim rethrow As Boolean = ExceptionPolicy.HandleException(errXml, "Log Only Policy")
            If (rethrow) Then
                Throw
            End If
        Catch err As Exception
            Dim rethrow As Boolean = ExceptionPolicy.HandleException(err, "Log Only Policy")
            If (rethrow) Then
                Throw
            End If
        End Try

    End Sub


#End Region

#Region " Section - Shape Data / Property "

    '<Section N="Property">
    ' <Row N="NewData">
    '  <Cell N="Value" V="StringData" U="STR" /> 
    '  <Cell N="Prompt" V="EnterStringData" /> 
    '  <Cell N="Label" V="NewData" /> 
    '  <Cell N="Format" V="" F="No Formula" /> 
    '  <Cell N="SortKey" V="01" /> 
    '  <Cell N="Type" V="0" /> 
    '  <Cell N="Invisible" V="0" F="No Formula" /> 
    '  <Cell N="Verify" V="0" F="No Formula" /> 
    '  <Cell N="DataLinked" V="0" F="No Formula" /> 
    '  <Cell N="LangID" V="en-US" /> 
    '  <Cell N="Calendar" V="0" F="No Formula" /> 
    ' </Row>
    '</Section>

    '
    '
    '
    Public arrShapeDataFields() As String = _
        {"Value", "Prompt", "Label", "Format", "SortKey", "Type", _
         "Invisible", "Verify", "DataLinked", "LangID", "Calendar"}

    '
    '
    '
    Private dictShapeDataFields As Dictionary(Of String, String)

    '
    '
    '
    Public Sub initDictShapeDataFields()
        If dictShapeDataFields Is Nothing Then
            dictShapeDataFields = New Dictionary(Of String, String)
        End If
        dictShapeDataFields.Clear()
        Dim visCell As stcCell = New stcCell
        visCell.Reset()
        visCell.cellName = "Value"
        visCell.cellValue = "StrData"
        visCell.cellUnits = "STR"
        dictShapeDataFields.Add("value", visCell.toXML)
        visCell.Reset()
        visCell.cellName = "Prompt"
        visCell.cellValue = ""
        dictShapeDataFields.Add("prompt", visCell.toXML)
        visCell.Reset()
        visCell.cellName = "Label"
        visCell.cellValue = ""
        dictShapeDataFields.Add("label", visCell.toXML)
        visCell.Reset()
        visCell.cellName = "Format"
        visCell.cellValue = ""
        visCell.cellFormula = "No Formula"
        dictShapeDataFields.Add("format", visCell.toXML)
        visCell.Reset()
        visCell.cellName = "SortKey"
        visCell.cellValue = ""
        dictShapeDataFields.Add("sortkey", visCell.toXML)
        visCell.Reset()
        visCell.cellName = "Type"
        visCell.cellValue = "0"
        visCell.cellFormula = "No Formula"
        dictShapeDataFields.Add("type", visCell.toXML)
        visCell.Reset()
        visCell.cellName = "Invisible"
        visCell.cellValue = "0"
        visCell.cellFormula = "No Formula"
        dictShapeDataFields.Add("invisible", visCell.toXML)
        visCell.Reset()
        visCell.cellName = "Verify"
        visCell.cellValue = "0"
        visCell.cellFormula = "No Formula"
        dictShapeDataFields.Add("verify", visCell.toXML)
        visCell.Reset()
        visCell.cellName = "DataLinked"
        visCell.cellValue = "0"
        visCell.cellFormula = "No Formula"
        dictShapeDataFields.Add("datalinked", visCell.toXML)
        visCell.Reset()
        visCell.cellName = "LangID"
        visCell.cellValue = "1033"
        visCell.cellFormula = "No Formula"
        dictShapeDataFields.Add("langid", visCell.toXML)
        visCell.Reset()
        visCell.cellName = "Calendar"
        visCell.cellValue = "0"
        visCell.cellFormula = "No Formula"
        dictShapeDataFields.Add("calendar", visCell.toXML)
    End Sub

    '
    '
    '
    Public Function createSectionProperty() As XElement
        Dim xelemReturn As XElement = New XElement("Section")
        xelemReturn.SetAttributeValue("N", "Property")
        Return xelemReturn
    End Function

    '
    '
    '
    Public Function createRowProperty _
        (ByVal strRowName As String, _
         Optional ByVal blnAddEmpty As Boolean = True, _
         Optional ByVal stcValue As stcCell = Nothing, _
         Optional ByVal stcPrompt As stcCell = Nothing, _
         Optional ByVal stcLabel As stcCell = Nothing, _
         Optional ByVal stcFormat As stcCell = Nothing, _
         Optional ByVal stcSortKey As stcCell = Nothing, _
         Optional ByVal stcType As stcCell = Nothing, _
         Optional ByVal stcInvisible As stcCell = Nothing, _
         Optional ByVal stcVerify As stcCell = Nothing, _
         Optional ByVal stcDataLinked As stcCell = Nothing, _
         Optional ByVal stcLangId As stcCell = Nothing, _
         Optional ByVal stcCalendar As stcCell = Nothing) _
     As XElement

        Dim xelemReturn As XElement = New XElement("Row")
        Dim cellNew As stcCell = Nothing


        initDictShapeDataFields()


        Try

            xelemReturn.SetAttributeValue("N", strRowName)

            For Each fldName In dictShapeDataFields
                Select Case LCase(fldName.Key)
                    Case "value"
                        If stcValue = Nothing Then
                            If blnAddEmpty = True Then
                                xelemReturn.Add(XElement.Load((XmlReader.Create(New StringReader(fldName.Value)))))
                            End If
                        Else
                            xelemReturn.Add(stcValue.writeXelement)
                        End If
                        Exit Select
                    Case "prompt"
                        If stcPrompt = Nothing Then
                            If blnAddEmpty = True Then
                                xelemReturn.Add(XElement.Load((XmlReader.Create(New StringReader(fldName.Value)))))
                            End If
                        Else
                            xelemReturn.Add(stcPrompt.writeXelement)
                        End If
                        Exit Select
                    Case "label"
                        If stcLabel = Nothing Then
                            If blnAddEmpty = True Then
                                xelemReturn.Add(XElement.Load((XmlReader.Create(New StringReader(fldName.Value)))))
                            End If
                        Else
                            xelemReturn.Add(stcLabel.writeXelement)
                        End If
                        Exit Select
                    Case "format"
                        If stcFormat = Nothing Then
                            If blnAddEmpty = True Then
                                xelemReturn.Add(XElement.Load((XmlReader.Create(New StringReader(fldName.Value)))))
                            End If
                        Else
                            xelemReturn.Add(stcFormat.writeXelement)
                        End If
                        Exit Select
                    Case "sortkey"
                        If stcSortKey = Nothing Then
                            If blnAddEmpty = True Then
                                xelemReturn.Add(XElement.Load((XmlReader.Create(New StringReader(fldName.Value)))))
                            End If
                        Else
                            xelemReturn.Add(stcSortKey.writeXelement)
                        End If
                        Exit Select
                    Case "type"
                        If stcType = Nothing Then
                            If blnAddEmpty = True Then
                                xelemReturn.Add(XElement.Load((XmlReader.Create(New StringReader(fldName.Value)))))
                            End If
                        Else
                            xelemReturn.Add(stcType.writeXelement)
                        End If
                        Exit Select
                    Case "invisible"
                        If stcInvisible = Nothing Then
                            If blnAddEmpty = True Then
                                xelemReturn.Add(XElement.Load((XmlReader.Create(New StringReader(fldName.Value)))))
                            End If
                        Else
                            xelemReturn.Add(stcInvisible.writeXelement)
                        End If
                        Exit Select
                    Case "verify"
                        If stcVerify = Nothing Then
                            If blnAddEmpty = True Then
                                xelemReturn.Add(XElement.Load((XmlReader.Create(New StringReader(fldName.Value)))))
                            End If
                        Else
                            xelemReturn.Add(stcVerify.writeXelement)
                        End If
                        Exit Select
                    Case "datalinked"
                        If stcDataLinked = Nothing Then
                            If blnAddEmpty = True Then
                                xelemReturn.Add(XElement.Load((XmlReader.Create(New StringReader(fldName.Value)))))
                            End If
                        Else
                            xelemReturn.Add(stcDataLinked.writeXelement)
                        End If
                        Exit Select
                    Case "langid"
                        If stcLangId = Nothing Then
                            If blnAddEmpty = True Then
                                xelemReturn.Add(XElement.Load((XmlReader.Create(New StringReader(fldName.Value)))))
                            End If
                        Else
                            xelemReturn.Add(stcLangId.writeXelement)
                        End If
                        Exit Select
                    Case "calendar"
                        If stcCalendar = Nothing Then
                            If blnAddEmpty = True Then
                                xelemReturn.Add(XElement.Load((XmlReader.Create(New StringReader(fldName.Value)))))
                            End If
                        Else
                            xelemReturn.Add(stcCalendar.writeXelement)
                        End If
                        Exit Select
                End Select
            Next fldName

 


        Catch errXml As XmlException
            Dim rethrow As Boolean = ExceptionPolicy.HandleException(errXml, "Log Only Policy")
            If (rethrow) Then
                Throw
            End If
        Catch err As Exception
            Dim rethrow As Boolean = ExceptionPolicy.HandleException(err, "Log Only Policy")
            If (rethrow) Then
                Throw
            End If
        End Try

        Return xelemReturn

    End Function


    '
    '
    '
    Public Sub addShapeDataNetworkAttributes()
        Try

            Dim xelemSection As XElement = Nothing
            Dim xelemNewSection As XElement = Nothing

            xelemSection = existsSection("Property")

            If xelemSection IsNot Nothing Then
                xelemNewSection = xelemSection
            Else
                xelemSection = createSectionProperty()
                Me.xDoc.Root.Add(xelemSection)
                xelemNewSection = xelemSection
            End If


            Dim newCell As stcCell = New stcCell
            Dim xelemRow As XElement = Nothing

            Dim cellValue As stcCell = New stcCell("Value", "", Nothing, "STR")
            Dim cellLabel As stcCell = New stcCell("Label", "netName", Nothing, Nothing)
            Dim cellPrompt As stcCell = New stcCell("Prompt", "XX.YY", Nothing, Nothing)
            Dim cellSortKey As stcCell = New stcCell("SortKey", "network", Nothing, Nothing)
            Dim xelemNewProp As XElement = Nothing

            If existsNamedRow(xelemNewSection, "netName") = False Then
                xelemNewProp = createRowProperty("netName", stcValue:=cellValue, stcPrompt:=cellPrompt, stcSortKey:=cellSortKey, stcLabel:=cellLabel)
                xelemNewSection.Add(xelemNewProp)
            End If


            If existsNamedRow(xelemNewSection, "domainName") = False Then
                cellLabel.cellValue = "domainName"
                cellValue.cellValue = ""
                cellPrompt.cellValue = "XX"
                xelemNewProp = createRowProperty("domainName", stcValue:=cellValue, stcPrompt:=cellPrompt, stcSortKey:=cellSortKey, stcLabel:=cellLabel)
                xelemNewSection.Add(xelemNewProp)
            End If


            If existsNamedRow(xelemNewSection, "ipAddress") = False Then
                cellLabel.cellValue = "ipAddress"
                cellValue.cellValue = ""
                cellPrompt.cellValue = "aaa.bbb.ccc.ddd"
                xelemNewProp = createRowProperty("ipAddress", stcValue:=cellValue, stcPrompt:=cellPrompt, stcSortKey:=cellSortKey, stcLabel:=cellLabel)
                xelemNewSection.Add(xelemNewProp)
            End If


            If existsNamedRow(xelemNewSection, "ipMask") = False Then
                cellLabel.cellValue = "ipMask"
                cellValue.cellValue = ""
                cellPrompt.cellValue = "www.xxx.yyy.zzz"
                xelemNewProp = createRowProperty("ipMask", stcValue:=cellValue, stcPrompt:=cellPrompt, stcSortKey:=cellSortKey, stcLabel:=cellLabel)
                xelemNewSection.Add(xelemNewProp)
            End If

            If existsNamedRow(xelemNewSection, "netStatus") = False Then
                cellLabel.cellValue = "netStatus"
                cellValue.cellValue = "netUnknown"
                cellPrompt.cellValue = ""
                xelemNewProp = createRowProperty("netStatus", stcValue:=cellValue, stcPrompt:=cellPrompt, stcSortKey:=cellSortKey, stcLabel:=cellLabel)
                xelemNewSection.Add(xelemNewProp)
            End If

            xelemSection.ReplaceWith(xelemNewSection)

        Catch errXml As XmlException
            Dim rethrow As Boolean = ExceptionPolicy.HandleException(errXml, "Log Only Policy")
            If (rethrow) Then
                Throw
            End If
        Catch err As Exception
            Dim rethrow As Boolean = ExceptionPolicy.HandleException(err, "Log Only Policy")
            If (rethrow) Then
                Throw
            End If
        End Try

    End Sub



#End Region

#Region " Section - Text "

    '<xsd:complexType name="Text_Type" mixed="true">
    '  <xsd:choice minOccurs="0" maxOccurs="unbounded">
    '    <xsd:element name="cp" type="cp_Type" minOccurs="0" maxOccurs="unbounded" />
    '    <xsd:element name="pp" type="pp_Type" minOccurs="0" maxOccurs="unbounded" />
    '    <xsd:element name="tp" type="tp_Type" minOccurs="0" maxOccurs="unbounded" />
    '    <xsd:element name="fld" type="fld_Type" minOccurs="0" maxOccurs="unbounded" />
    '  </xsd:choice>
    '</xsd:complexType>

    ' check the visio 2010 sdk documentation (xml documentation)
    ' cp = character properties index
    ' pp = paragraph properties index
    ' tp = tab properties index
    ' fld = field data pointer 

    '<Char IX="0"/> 
    '<Char IX="1 "/>
    '<Para IX="0 "><HorzAlign>1</HorzAlign></Para>
    '<Para IX="1 "><IndLeft>0.3</IndLeft><HorzAlign>0</HorzAlign></Para>
    '<Tabs IX="0 "/>
    '…
    '…
    '<Text><cp IX="0" /><pp IX="0" /><tp IX="0" />This paragraph is center aligned.<cp IX="1" />
    '<pp IX="1" />This paragraph is left aligned, with a 0.3 in. left indent.</Text>


    '
    ' return the text xelement (it is not a section in visio 15 schema) from the shape if it exists
    '
    Public Function getSectionText() As XElement


        Dim xelemReturn As XElement = Nothing

        Try

            Dim qryProperties = Me.xDoc.Descendants

            ' start the element drilldown
            Dim listOfElements As IEnumerable(Of XElement) = _
                    From elem In qryProperties.Elements() _
                    Select elem
            For Each elem As XElement In listOfElements
                Select Case LCase(elem.Name.LocalName)
                    Case "text"
                        xelemReturn = elem
                        Exit For
                End Select
            Next elem

        Catch errXml As XmlException
            Dim rethrow As Boolean = ExceptionPolicy.HandleException(errXml, "Log Only Policy")
            If (rethrow) Then
                Throw
            End If
        Catch err As Exception
            Dim rethrow As Boolean = ExceptionPolicy.HandleException(err, "Log Only Policy")
            If (rethrow) Then
                Throw
            End If
        End Try

        Return xelemReturn

    End Function


    '
    '
    '
    Public Function createSectionText() As XElement
        Dim xelemReturn As XElement = New XElement("Section")
        xelemReturn.SetAttributeValue("N", "Text")
        Return xelemReturn

    End Function

#End Region

#Region " Section - Character "

    ' based on v2010

    '<xsd:complexType name="Char_Type">
    ' <xsd:complexContent>
    '  <xsd:extension base="IndexedRow_Type">
    '   <xsd:sequence>
    '    <xsd:element name="Font" type="Font_Type" minOccurs="0"/>
    '    <xsd:element name="Color" type="Color_Type" minOccurs="0"/>
    '    <xsd:element name="Style" type="Style_Type" minOccurs="0"/>
    '    <xsd:element name="Case" type="Case_Type" minOccurs="0"/>
    '    <xsd:element name="Pos" type="Pos_Type" minOccurs="0"/>
    '    <xsd:element name="FontScale" type="FontScale_Type" minOccurs="0"/>
    '    <xsd:element name="Locale" type="Locale_Type" minOccurs="0"/>
    '    <xsd:element name="Size" type="Size_Type" minOccurs="0"/>
    '    <xsd:element name="DblUnderline" type="DblUnderline_Type" minOccurs="0"/>
    '    <xsd:element name="Overline" type="Overline_Type" minOccurs="0"/>
    '    <xsd:element name="Strikethru" type="Strikethru_Type" minOccurs="0"/>
    '    <xsd:element name="Highlight" type="Highlight_Type" minOccurs="0"/>
    '    <xsd:element name="Perpendicular" type="Perpendicular_Type" minOccurs="0"/>
    '    <xsd:element name="DoubleStrikethrough" type="DoubleStrikethrough_Type" minOccurs="0"/>
    '    <xsd:element name="RTLText" type="RTLText_Type" minOccurs="0"/>
    '    <xsd:element name="UseVertical" type="UseVertical_Type" minOccurs="0"/>
    '    <xsd:element name="Letterspace" type="Letterspace_Type" minOccurs="0"/>
    '    <xsd:element name="ColorTrans" type="ColorTrans_Type" minOccurs="0"/>
    '    <xsd:element name="AsianFont" type="AsianFont_Type" minOccurs="0"/>
    '    <xsd:element name="ComplexScriptFont" type="ComplexScriptFont_Type" minOccurs="0"/>
    '    <xsd:element name="LocalizeFont" type="LocalizeFont_Type" minOccurs="0"/>
    '    <xsd:element name="ComplexScriptSize" type="ComplexScriptSize_Type" minOccurs="0"/>
    '    <xsd:element name="LangID" type="LangID_Type" minOccurs="0"/>
    '   </xsd:sequence>
    '  </xsd:extension>
    ' </xsd:complexContent>
    '</xsd:complexType>


    '<Section N="Character">
    '   <Row IX="0" /> 
    '</Section>


    Public Structure stcFlagCharStyle

        <FlagsAttribute()>
        Public Enum Style As ULong
            visBold = &H1
            visItalic = &H2
            visUnderline = &H4
            visSmallCaps = &H8
        End Enum

    End Structure

    '
    '
    '
    Public arrCharacterFields() As String = _
        {"Font", "Color", "Style", "Case", "Pos", "FontScale", _
         "Size", "DblUnderline", "Overline", "Strikethru", "Highlight", "Perpendicular", _
         "DoubleStrikethrough", "RTLText", "UseVertical", "Letterspace", _
         "ColorTrans", "AsianFont", "ComplexScriptFont", "LocalizeFont", "LangID"}

    '
    '
    '
    Private dictCharacterFields As Dictionary(Of String, String)

    '
    '
    '
    Public Sub initDictCharacterFields()
        If dictCharacterFields Is Nothing Then
            dictCharacterFields = New Dictionary(Of String, String)
        End If
        dictCharacterFields.Clear()
        Dim visCell As stcCell = New stcCell

        visCell.Reset()
        visCell.cellName = "Font"
        visCell.cellValue = "4"
        dictCharacterFields.Add("font", visCell.toXML)

        visCell.Reset()
        visCell.cellName = "Color"
        visCell.cellValue = "#000000"
        visCell.cellFormula = "THEME(""TextColor"")"
        dictCharacterFields.Add("color", visCell.toXML)

        visCell.Reset()
        visCell.cellName = "Style"
        visCell.cellValue = "0"
        dictCharacterFields.Add("style", visCell.toXML)

        visCell.Reset()
        visCell.cellName = "Case"
        visCell.cellValue = "0"
        dictCharacterFields.Add("case", visCell.toXML)

        visCell.Reset()
        visCell.cellName = "Pos"
        visCell.cellValue = "0"
        dictCharacterFields.Add("pos", visCell.toXML)

        visCell.Reset()
        visCell.cellName = "FontScale"
        visCell.cellValue = "100%"
        dictCharacterFields.Add("fontscale", visCell.toXML)

        ' where size uses pt as the number the value is equal to
        ' 1/72 of an inch for each point
        visCell.Reset()
        visCell.cellName = "Size"
        visCell.cellValue = "0.1666666666666667"
        visCell.cellUnits = "PT"
        dictCharacterFields.Add("size", visCell.toXML)

        visCell.Reset()
        visCell.cellName = "DblUnderline"
        visCell.cellValue = "0"
        dictCharacterFields.Add("dblunderline", visCell.toXML)

        visCell.Reset()
        visCell.cellName = "Overline"
        visCell.cellValue = "0"
        dictCharacterFields.Add("overline", visCell.toXML)

        visCell.Reset()
        visCell.cellName = "Strikethru"
        visCell.cellValue = "0"
        dictCharacterFields.Add("strikethru", visCell.toXML)

        visCell.Reset()
        visCell.cellName = "Highlight"
        visCell.cellValue = "0"
        dictCharacterFields.Add("highlight", visCell.toXML)

        visCell.Reset()
        visCell.cellName = "Perpendicular"
        visCell.cellValue = "0"
        dictCharacterFields.Add("perpendicular", visCell.toXML)

        visCell.Reset()
        visCell.cellName = "DoubleStrikethrough"
        visCell.cellValue = "0"
        dictCharacterFields.Add("doublestrikethrough", visCell.toXML)

        visCell.Reset()
        visCell.cellName = "RTLText"
        visCell.cellValue = "0"
        dictCharacterFields.Add("rtltext", visCell.toXML)

        visCell.Reset()
        visCell.cellName = "UseVertical"
        visCell.cellValue = "0"
        dictCharacterFields.Add("usevertical", visCell.toXML)

        visCell.Reset()
        visCell.cellName = "Letterspace"
        visCell.cellValue = "0"
        dictCharacterFields.Add("letterspace", visCell.toXML)

        visCell.Reset()
        visCell.cellName = "Colortrans"
        visCell.cellValue = "0"
        dictCharacterFields.Add("colortrans", visCell.toXML)

        visCell.Reset()
        visCell.cellName = "AsianFont"
        visCell.cellValue = "0"
        dictCharacterFields.Add("asianfont", visCell.toXML)

        visCell.Reset()
        visCell.cellName = "ComplexScriptFont"
        visCell.cellValue = "0"
        dictCharacterFields.Add("complexscriptfont", visCell.toXML)

        visCell.Reset()
        visCell.cellName = "LocalizeFont"
        visCell.cellValue = "0"
        dictCharacterFields.Add("localizefont", visCell.toXML)

        visCell.Reset()
        visCell.cellName = "ComplexScriptSize"
        visCell.cellValue = "-1"
        dictCharacterFields.Add("complexscriptsize", visCell.toXML)

        visCell.Reset()
        visCell.cellName = "LangID"
        visCell.cellValue = "1033"
        dictCharacterFields.Add("langid", visCell.toXML)


    End Sub

    '
    '
    '
    Public Function createSectionCharacter(Optional ByVal blnInit As Boolean = False) As XElement
        Dim xelemReturn As XElement = New XElement("Section")
        xelemReturn.SetAttributeValue("N", "Character")

        If blnInit = True Then
            Dim xelemRowZero As XElement = Nothing
            xelemRowZero = createRowCharacter(0, False)
            xelemReturn.Add(xelemRowZero)
        End If

        Return xelemReturn

    End Function

    '
    '
    '
    Public Function createRowCharacter _
        (ByVal intRowIndex As Integer, _
         Optional ByVal blnAddEmpty As Boolean = True, _
         Optional ByVal stcFont As stcCell = Nothing, _
         Optional ByVal stcColor As stcCell = Nothing, _
         Optional ByVal stcStyle As stcCell = Nothing, _
         Optional ByVal stcCase As stcCell = Nothing, _
         Optional ByVal stcPos As stcCell = Nothing, _
         Optional ByVal stcFontScale As stcCell = Nothing, _
         Optional ByVal stcSize As stcCell = Nothing, _
         Optional ByVal stcDblUnderline As stcCell = Nothing, _
         Optional ByVal stcOverline As stcCell = Nothing, _
         Optional ByVal stcStrikethru As stcCell = Nothing, _
         Optional ByVal stcHighlight As stcCell = Nothing, _
         Optional ByVal stcPerpendicular As stcCell = Nothing, _
         Optional ByVal stcDoubleStrikeghrough As stcCell = Nothing, _
         Optional ByVal stcRTLText As stcCell = Nothing, _
         Optional ByVal stcUseVertical As stcCell = Nothing, _
         Optional ByVal stcLetterspace As stcCell = Nothing, _
         Optional ByVal stcColorTrans As stcCell = Nothing, _
         Optional ByVal stcAsianFont As stcCell = Nothing, _
         Optional ByVal stcComplexScriptFont As stcCell = Nothing, _
         Optional ByVal stcLocalizeFont As stcCell = Nothing, _
         Optional ByVal stcLangID As stcCell = Nothing) _
     As XElement

        Dim xelemReturn As XElement = New XElement("Row")
        Dim cellNew As stcCell = Nothing

        initDictCharacterFields()

        Try

            xelemReturn.SetAttributeValue("IX", intRowIndex)


            For Each fldName In dictCharacterFields
                Select Case LCase(fldName.Key)

                    Case "font"
                        If stcFont = Nothing Then
                            If blnAddEmpty = True Then
                                xelemReturn.Add(XElement.Load((XmlReader.Create(New StringReader(fldName.Value)))))
                            End If
                        Else
                            xelemReturn.Add(stcFont.writeXelement)
                        End If
                        Exit Select

                    Case "color"
                        If stcColor = Nothing Then
                            If blnAddEmpty = True Then
                                xelemReturn.Add(XElement.Load((XmlReader.Create(New StringReader(fldName.Value)))))
                            End If
                        Else
                            xelemReturn.Add(stcColor.writeXelement)
                        End If
                        Exit Select

                    Case "style"
                        If stcStyle = Nothing Then
                            If blnAddEmpty = True Then
                                xelemReturn.Add(XElement.Load((XmlReader.Create(New StringReader(fldName.Value)))))
                            End If
                        Else
                            xelemReturn.Add(stcStyle.writeXelement)
                        End If
                        Exit Select

                    Case "case"
                        If stcCase = Nothing Then
                            If blnAddEmpty = True Then
                                xelemReturn.Add(XElement.Load((XmlReader.Create(New StringReader(fldName.Value)))))
                            End If
                        Else
                            xelemReturn.Add(stcCase.writeXelement)
                        End If
                        Exit Select

                    Case "pos"
                        If stcPos = Nothing Then
                            If blnAddEmpty = True Then
                                xelemReturn.Add(XElement.Load((XmlReader.Create(New StringReader(fldName.Value)))))
                            End If
                        Else
                            xelemReturn.Add(stcPos.writeXelement)
                        End If
                        Exit Select

                    Case "fontscale"
                        If stcFontScale = Nothing Then
                            If blnAddEmpty = True Then
                                xelemReturn.Add(XElement.Load((XmlReader.Create(New StringReader(fldName.Value)))))
                            End If
                        Else
                            xelemReturn.Add(stcFontScale.writeXelement)
                        End If
                        Exit Select

                    Case "size"
                        If stcSize = Nothing Then
                            If blnAddEmpty = True Then
                                xelemReturn.Add(XElement.Load((XmlReader.Create(New StringReader(fldName.Value)))))
                            End If
                        Else
                            xelemReturn.Add(stcSize.writeXelement)
                        End If
                        Exit Select

                    Case "dblunderline"
                        If stcDblUnderline = Nothing Then
                            If blnAddEmpty = True Then
                                xelemReturn.Add(XElement.Load((XmlReader.Create(New StringReader(fldName.Value)))))
                            End If
                        Else
                            xelemReturn.Add(stcDblUnderline.writeXelement)
                        End If
                        Exit Select

                    Case "overline"
                        If stcOverline = Nothing Then
                            If blnAddEmpty = True Then
                                xelemReturn.Add(XElement.Load((XmlReader.Create(New StringReader(fldName.Value)))))
                            End If
                        Else
                            xelemReturn.Add(stcOverline.writeXelement)
                        End If
                        Exit Select

                    Case "strikethru"
                        If stcStrikethru = Nothing Then
                            If blnAddEmpty = True Then
                                xelemReturn.Add(XElement.Load((XmlReader.Create(New StringReader(fldName.Value)))))
                            End If
                        Else
                            xelemReturn.Add(stcStrikethru.writeXelement)
                        End If
                        Exit Select

                    Case "highlight"
                        If stcHighlight = Nothing Then
                            If blnAddEmpty = True Then
                                xelemReturn.Add(XElement.Load((XmlReader.Create(New StringReader(fldName.Value)))))
                            End If
                        Else
                            xelemReturn.Add(stcHighlight.writeXelement)
                        End If
                        Exit Select

                    Case "perpendicular"
                        If stcPerpendicular = Nothing Then
                            If blnAddEmpty = True Then
                                xelemReturn.Add(XElement.Load((XmlReader.Create(New StringReader(fldName.Value)))))
                            End If
                        Else
                            xelemReturn.Add(stcPerpendicular.writeXelement)
                        End If
                        Exit Select

                    Case "doublestrikethrough"
                        If stcDoubleStrikeghrough = Nothing Then
                            If blnAddEmpty = True Then
                                xelemReturn.Add(XElement.Load((XmlReader.Create(New StringReader(fldName.Value)))))
                            End If
                        Else
                            xelemReturn.Add(stcDoubleStrikeghrough.writeXelement)
                        End If
                        Exit Select

                    Case "rtltext"
                        If stcRTLText = Nothing Then
                            If blnAddEmpty = True Then
                                xelemReturn.Add(XElement.Load((XmlReader.Create(New StringReader(fldName.Value)))))
                            End If
                        Else
                            xelemReturn.Add(stcRTLText.writeXelement)
                        End If
                        Exit Select

                    Case "usevertical"
                        If stcUseVertical = Nothing Then
                            If blnAddEmpty = True Then
                                xelemReturn.Add(XElement.Load((XmlReader.Create(New StringReader(fldName.Value)))))
                            End If
                        Else
                            xelemReturn.Add(stcUseVertical.writeXelement)
                        End If
                        Exit Select

                    Case "letterspace"
                        If stcLetterspace = Nothing Then
                            If blnAddEmpty = True Then
                                xelemReturn.Add(XElement.Load((XmlReader.Create(New StringReader(fldName.Value)))))
                            End If
                        Else
                            xelemReturn.Add(stcLetterspace.writeXelement)
                        End If
                        Exit Select

                    Case "colortrans"
                        If stcColorTrans = Nothing Then
                            If blnAddEmpty = True Then
                                xelemReturn.Add(XElement.Load((XmlReader.Create(New StringReader(fldName.Value)))))
                            End If
                        Else
                            xelemReturn.Add(stcColorTrans.writeXelement)
                        End If
                        Exit Select

                    Case "asianfont"
                        If stcAsianFont = Nothing Then
                            If blnAddEmpty = True Then
                                xelemReturn.Add(XElement.Load((XmlReader.Create(New StringReader(fldName.Value)))))
                            End If
                        Else
                            xelemReturn.Add(stcAsianFont.writeXelement)
                        End If
                        Exit Select

                    Case "complexscriptfont"
                        If stcComplexScriptFont = Nothing Then
                            If blnAddEmpty = True Then
                                xelemReturn.Add(XElement.Load((XmlReader.Create(New StringReader(fldName.Value)))))
                            End If
                        Else
                            xelemReturn.Add(stcComplexScriptFont.writeXelement)
                        End If
                        Exit Select

                    Case "localizefont"
                        If stcLocalizeFont = Nothing Then
                            If blnAddEmpty = True Then
                                xelemReturn.Add(XElement.Load((XmlReader.Create(New StringReader(fldName.Value)))))
                            End If
                        Else
                            xelemReturn.Add(stcLocalizeFont.writeXelement)
                        End If
                        Exit Select

                    Case "langic"
                        If stcLangID = Nothing Then
                            If blnAddEmpty = True Then
                                xelemReturn.Add(XElement.Load((XmlReader.Create(New StringReader(fldName.Value)))))
                            End If
                        Else
                            xelemReturn.Add(stcLangID.writeXelement)
                        End If
                        Exit Select


                End Select
            Next fldName


        Catch errXml As XmlException
            Dim rethrow As Boolean = ExceptionPolicy.HandleException(errXml, "Log Only Policy")
            If (rethrow) Then
                Throw
            End If
        Catch err As Exception
            Dim rethrow As Boolean = ExceptionPolicy.HandleException(err, "Log Only Policy")
            If (rethrow) Then
                Throw
            End If
        End Try


        Return xelemReturn
    End Function




#End Region

#Region " Section - Paragraph "

    ' based upon v2010

    '<xsd:complexType name="Para_Type">
    ' <xsd:complexContent>
    '  <xsd:extension base="IndexedRow_Type">
    '   <xsd:sequence>
    '    <xsd:element name="IndFirst" type="IndFirst_Type" minOccurs="0"/>
    '    <xsd:element name="IndLeft" type="IndLeft_Type" minOccurs="0"/>
    '    <xsd:element name="IndRight" type="IndRight_Type" minOccurs="0"/>
    '    <xsd:element name="SpLine" type="SpLine_Type" minOccurs="0"/>
    '    <xsd:element name="SpBefore" type="SpBefore_Type" minOccurs="0"/>
    '    <xsd:element name="SpAfter" type="SpAfter_Type" minOccurs="0"/>
    '    <xsd:element name="HorzAlign" type="HorzAlign_Type" minOccurs="0"/>
    '    <xsd:element name="Bullet" type="Bullet_Type" minOccurs="0"/>
    '    <xsd:element name="BulletStr" type="BulletStr_Type" minOccurs="0"/>
    '    <xsd:element name="BulletFont" type="BulletFont_Type" minOccurs="0"/>
    '    <xsd:element name="LocalizeBulletFont" type="LocalizeBulletFont_Type" minOccurs="0"/>
    '    <xsd:element name="BulletFontSize" type="BulletFontSize_Type" minOccurs="0"/>
    '    <xsd:element name="TextPosAfterBullet" type="TextPosAfterBullet_Type" minOccurs="0"/>
    '    <xsd:element name="Flags" type="Flags_Type" minOccurs="0"/>
    '   </xsd:sequence>
    '  </xsd:extension>
    ' </xsd:complexContent>
    '</xsd:complexType>



    '<Section N="Paragraph">
    '    <Row IX="0" /> 
    '</Section>

    '
    ' enumerations for paragraph horizontal alignment
    '
    Public Enum msoParagraphAlign
        msoAlignCenter = 1
        msoAlignDistribute = 4
        msoAlignJustify = 3
        msoAlignJustifyLow = 5
        msoAlignLeft = 0
        msoAlignMixed = -2
        msoAlignRight = 2
        msoAlignThaiDistribute = 5
    End Enum

    '
    ' paragraph row field names
    '
    Public arrParagraphFields() As String = _
        {"IndFirst", "IndLeft", "IndRight", "SpLine", "SpBefore", "SpAfter", _
         "HorzAlign", "Bullet", "BulletStr", "BulletFont", "LocalizeBulletFont", _
         "BulletFontSize", "TextPosAfterBullet", "Flags"}

    '
    '
    '
    Private dictParagraphFields As Dictionary(Of String, String)

    '
    '
    '
    Public Sub initDictParagraphFields()
        If dictParagraphFields Is Nothing Then
            dictParagraphFields = New Dictionary(Of String, String)
        End If
        dictParagraphFields.Clear()
        Dim visCell As stcCell = New stcCell


        visCell.Reset()
        visCell.cellName = "IndFirst"
        visCell.cellValue = "0"
        visCell.cellUnits = "IN"
        dictParagraphFields.Add("indfirst", visCell.toXML)

        visCell.Reset()
        visCell.cellName = "IndLeft"
        visCell.cellValue = "0"
        visCell.cellUnits = "IN"
        dictParagraphFields.Add("indleft", visCell.toXML)

        visCell.Reset()
        visCell.cellName = "IndRight"
        visCell.cellValue = "0"
        visCell.cellUnits = "IN"
        dictParagraphFields.Add("indright", visCell.toXML)

        visCell.Reset()
        visCell.cellName = "SpLine"
        visCell.cellValue = "-120%"
        dictParagraphFields.Add("spline", visCell.toXML)

        visCell.Reset()
        visCell.cellName = "SpBefore"
        visCell.cellValue = "0"
        visCell.cellUnits = "PT"
        dictParagraphFields.Add("spbefore", visCell.toXML)

        visCell.Reset()
        visCell.cellName = "SpAfter"
        visCell.cellValue = "0"
        visCell.cellUnits = "PT"
        dictParagraphFields.Add("spafter", visCell.toXML)

        visCell.Reset()
        visCell.cellName = "HorzAlign"
        visCell.cellValue = "0"
        dictParagraphFields.Add("horzalign", visCell.toXML)

        visCell.Reset()
        visCell.cellName = "Bullet"
        visCell.cellValue = "0"
        dictParagraphFields.Add("bullet", visCell.toXML)

        visCell.Reset()
        visCell.cellName = "BulletStr"
        visCell.cellValue = ""
        dictParagraphFields.Add("bulletstr", visCell.toXML)

        visCell.Reset()
        visCell.cellName = "BulletFont"
        visCell.cellValue = "0"
        dictParagraphFields.Add("bulletfont", visCell.toXML)

        visCell.Reset()
        visCell.cellName = "LocalizeBulletFont"
        visCell.cellValue = "0"
        dictParagraphFields.Add("localizebulletfont", visCell.toXML)

        visCell.Reset()
        visCell.cellName = "TextPosAFterBullet"
        visCell.cellValue = "0"
        visCell.cellUnits = "IN"
        dictParagraphFields.Add("textposafterbullet", visCell.toXML)

        visCell.Reset()
        visCell.cellName = "BulletFontSize"
        visCell.cellValue = "-100%"
        dictParagraphFields.Add("bulletfontsize", visCell.toXML)

        visCell.Reset()
        visCell.cellName = "Flags"
        visCell.cellValue = "0"
        dictParagraphFields.Add("flags", visCell.toXML)

    End Sub

    '
    '
    '
    Public Function createSectionParagraph(Optional ByVal blnInit As Boolean = False) As XElement
        Dim xelemReturn As XElement = New XElement("Section")
        xelemReturn.SetAttributeValue("N", "Paragraph")

        If blnInit = True Then
            Dim xelemRowZero As XElement = Nothing
            xelemRowZero = createRowParagraph(0, False)
            xelemReturn.Add(xelemRowZero)
        End If

        Return xelemReturn
    End Function

    '
    '
    '
    Public Function createRowParagraph _
        (ByVal intRowIndex As Integer, _
         Optional ByVal blnAddEmpty As Boolean = True, _
         Optional ByVal stcIndFirst As stcCell = Nothing, _
         Optional ByVal stcIndLeft As stcCell = Nothing, _
         Optional ByVal stcIndRight As stcCell = Nothing, _
         Optional ByVal stcSpLine As stcCell = Nothing, _
         Optional ByVal stcSpBefore As stcCell = Nothing, _
         Optional ByVal stcSpAfter As stcCell = Nothing, _
         Optional ByVal stcHorzAlign As stcCell = Nothing, _
         Optional ByVal stcBullet As stcCell = Nothing, _
         Optional ByVal stcBulletStr As stcCell = Nothing, _
         Optional ByVal stcBulletFont As stcCell = Nothing, _
         Optional ByVal stcLocalizeBulletFont As stcCell = Nothing, _
         Optional ByVal stcBulletFontSize As stcCell = Nothing, _
         Optional ByVal stcTextPosAfterBullet As stcCell = Nothing, _
         Optional ByVal stcFlags As stcCell = Nothing) _
     As XElement

        Dim xelemReturn As XElement = New XElement("Row")
        Dim cellNew As stcCell = Nothing

        initDictParagraphFields()

        Try

            xelemReturn.SetAttributeValue("IX", intRowIndex)


            For Each fldName In dictParagraphFields
                Select Case LCase(fldName.Key)

                    Case "indfirst"
                        If stcIndFirst = Nothing Then
                            If blnAddEmpty = True Then
                                xelemReturn.Add(XElement.Load((XmlReader.Create(New StringReader(fldName.Value)))))
                            End If
                        Else
                            xelemReturn.Add(stcIndFirst.writeXelement)
                        End If
                        Exit Select

                    Case "indleft"
                        If stcIndLeft = Nothing Then
                            If blnAddEmpty = True Then
                                xelemReturn.Add(XElement.Load((XmlReader.Create(New StringReader(fldName.Value)))))
                            End If
                        Else
                            xelemReturn.Add(stcIndLeft.writeXelement)
                        End If
                        Exit Select

                    Case "indright"
                        If stcIndRight = Nothing Then
                            If blnAddEmpty = True Then
                                xelemReturn.Add(XElement.Load((XmlReader.Create(New StringReader(fldName.Value)))))
                            End If
                        Else
                            xelemReturn.Add(stcIndRight.writeXelement)
                        End If
                        Exit Select

                    Case "spline"
                        If stcSpLine = Nothing Then
                            If blnAddEmpty = True Then
                                xelemReturn.Add(XElement.Load((XmlReader.Create(New StringReader(fldName.Value)))))
                            End If
                        Else
                            xelemReturn.Add(stcSpLine.writeXelement)
                        End If
                        Exit Select

                    Case "spbefore"
                        If stcSpBefore = Nothing Then
                            If blnAddEmpty = True Then
                                xelemReturn.Add(XElement.Load((XmlReader.Create(New StringReader(fldName.Value)))))
                            End If
                        Else
                            xelemReturn.Add(stcSpBefore.writeXelement)
                        End If
                        Exit Select

                    Case "spafter"
                        If stcSpAfter = Nothing Then
                            If blnAddEmpty = True Then
                                xelemReturn.Add(XElement.Load((XmlReader.Create(New StringReader(fldName.Value)))))
                            End If
                        Else
                            xelemReturn.Add(stcSpAfter.writeXelement)
                        End If
                        Exit Select

                    Case "horzalign"
                        If stcHorzAlign = Nothing Then
                            If blnAddEmpty = True Then
                                xelemReturn.Add(XElement.Load((XmlReader.Create(New StringReader(fldName.Value)))))
                            End If
                        Else
                            xelemReturn.Add(stcHorzAlign.writeXelement)
                        End If
                        Exit Select

                    Case "bullet"
                        If stcBullet = Nothing Then
                            If blnAddEmpty = True Then
                                xelemReturn.Add(XElement.Load((XmlReader.Create(New StringReader(fldName.Value)))))
                            End If
                        Else
                            xelemReturn.Add(stcBullet.writeXelement)
                        End If
                        Exit Select

                    Case "bulletstr"
                        If stcBulletStr = Nothing Then
                            If blnAddEmpty = True Then
                                xelemReturn.Add(XElement.Load((XmlReader.Create(New StringReader(fldName.Value)))))
                            End If
                        Else
                            xelemReturn.Add(stcBulletStr.writeXelement)
                        End If
                        Exit Select

                    Case "bulletfont"
                        If stcBulletFont = Nothing Then
                            If blnAddEmpty = True Then
                                xelemReturn.Add(XElement.Load((XmlReader.Create(New StringReader(fldName.Value)))))
                            End If
                        Else
                            xelemReturn.Add(stcBulletFont.writeXelement)
                        End If
                        Exit Select

                    Case "localizebulletfont"
                        If stcLocalizeBulletFont = Nothing Then
                            If blnAddEmpty = True Then
                                xelemReturn.Add(XElement.Load((XmlReader.Create(New StringReader(fldName.Value)))))
                            End If
                        Else
                            xelemReturn.Add(stcLocalizeBulletFont.writeXelement)
                        End If
                        Exit Select

                    Case "bulletfontsize"
                        If stcBulletFontSize = Nothing Then
                            If blnAddEmpty = True Then
                                xelemReturn.Add(XElement.Load((XmlReader.Create(New StringReader(fldName.Value)))))
                            End If
                        Else
                            xelemReturn.Add(stcBulletFontSize.writeXelement)
                        End If
                        Exit Select

                    Case "textposafterbullet"
                        If stcTextPosAfterBullet = Nothing Then
                            If blnAddEmpty = True Then
                                xelemReturn.Add(XElement.Load((XmlReader.Create(New StringReader(fldName.Value)))))
                            End If
                        Else
                            xelemReturn.Add(stcTextPosAfterBullet.writeXelement)
                        End If
                        Exit Select

                    Case "flags"
                        If stcFlags = Nothing Then
                            If blnAddEmpty = True Then
                                xelemReturn.Add(XElement.Load((XmlReader.Create(New StringReader(fldName.Value)))))
                            End If
                        Else
                            xelemReturn.Add(stcFlags.writeXelement)
                        End If
                        Exit Select

                End Select
            Next fldName

        Catch errXml As XmlException
            Dim rethrow As Boolean = ExceptionPolicy.HandleException(errXml, "Log Only Policy")
            If (rethrow) Then
                Throw
            End If
        Catch err As Exception
            Dim rethrow As Boolean = ExceptionPolicy.HandleException(err, "Log Only Policy")
            If (rethrow) Then
                Throw
            End If
        End Try


        Return xelemReturn
    End Function

#End Region

#Region " Section - FieldData "


        '<Section N="Field">
        ' <Row IX="0">
        '  <Cell N="Value" V="ShapeA" U="STR" F="NAME()" /> 
        '  <Cell N="Format" V="@" U="STR" F="FIELDPICTURE(37)" /> 
        '  <Cell N="Type" V="0" /> 
        '  <Cell N="Calendar" V="0" /> 
        '  <Cell N="ObjectKind" V="0" /> 
        ' </Row>
        '</Section>

        '<xsd:complexType name="Field_Type">
        '	<xsd:complexContent>
        '		<xsd:extension base="IndexedRow_Type">
        '			<xsd:sequence>
        '				<xsd:element name="Value" type="Value_Type" minOccurs="0"/>
        '				<xsd:element name="EditMode" type="EditMode_Type" minOccurs="0"/>
        '				<xsd:element name="Format" type="Format_Type" minOccurs="0"/>
        '				<xsd:element name="Type" type="Type_Type" minOccurs="0"/>
        '				<xsd:element name="UICat" type="UICat_Type" minOccurs="0"/>
        '				<xsd:element name="UICod" type="UICod_Type" minOccurs="0"/>
        '				<xsd:element name="UIFmt" type="UIFmt_Type" minOccurs="0"/>
        '				<xsd:element name="Calendar" type="Calendar_Type" minOccurs="0"/>
        '				<xsd:element name="ObjectKind" type="ObjectKind_Type" minOccurs="0"/>
        '			</xsd:sequence>
        '		</xsd:extension>
        '	</xsd:complexContent>
        '</xsd:complexType>

        Public arrFieldDataFields() As String = _
        {"Value", "EditMode", "Format", "Type", "UICat", "UICod", "UIFmt", "Calendar", "ObjectKind"}

        Private dictFieldDataFields As Dictionary(Of String, String)

        '
        '
        '
    Public Sub initDictFieldDataFields()
        If dictFieldDataFields Is Nothing Then
            dictFieldDataFields = New Dictionary(Of String, String)
        Else
            dictFieldDataFields = Nothing
            dictFieldDataFields = New Dictionary(Of String, String)
        End If
        dictFieldDataFields.Clear()
        Dim visCell As stcCell = New stcCell
        visCell.Reset()
        visCell.cellName = "Value"
        visCell.cellValue = "NV"
        ' default it to the shape name
        visCell.cellFormula = "NAME()"
        visCell.cellUnits = "STR"
        dictFieldDataFields.Add("Value", visCell.toXML)
        visCell.cellName = "EditMode"
        visCell.cellValue = ""
        visCell.cellFormula = "No Formula"
        dictFieldDataFields.Add("EditMode", visCell.toXML)
        visCell.cellName = "Format"
        visCell.cellValue = "@"
        visCell.cellFormula = "FIELDPICTURE(37)"
        visCell.cellUnits = "STR"
        dictFieldDataFields.Add("Format", visCell.toXML)
        visCell.cellName = "Type"
        visCell.cellValue = "0"
        dictFieldDataFields.Add("Format", visCell.toXML)
        visCell.cellName = "UICat"
        visCell.cellValue = "0"
        dictFieldDataFields.Add("UICat", visCell.toXML)
        visCell.cellName = "UICod"
        visCell.cellValue = "0"
        dictFieldDataFields.Add("UICod", visCell.toXML)
        visCell.cellName = "UIFmt"
        visCell.cellValue = "0"
        dictFieldDataFields.Add("UIFmt", visCell.toXML)
        visCell.cellName = "Calendar"
        visCell.cellValue = "0"
        dictFieldDataFields.Add("Calendar", visCell.toXML)
        visCell.cellName = "ObjectKind"
        visCell.cellValue = "0"
        dictFieldDataFields.Add("ObjectKind", visCell.toXML)

    End Sub



    '
    ' pass in field data section and a row index to return the row
    '
    Public Function getRowFieldData _
        (ByRef xelemSection As XElement, _
         ByVal intRowIndex As Integer) _
        As XElement

        Dim xelemReturn As XElement = Nothing

        Try

            If xelemSection Is Nothing Then GoTo ExitHandler

            ' start the element drilldown
            Dim listOfElements As IEnumerable(Of XElement) = _
                    From elem In xelemSection.Elements() _
                    Select elem

            If listOfElements Is Nothing Then GoTo ExitHandler

            For Each elem As XElement In listOfElements
                Select Case LCase(elem.Name.LocalName)
                    Case "row"
                        If elem.@IX = CStr(intRowIndex) Then
                            xelemReturn = elem
                        End If
                        Exit For
                End Select
            Next elem

        Catch errXml As XmlException
            Dim rethrow As Boolean = ExceptionPolicy.HandleException(errXml, "Log Only Policy")
            If (rethrow) Then
                Throw
            End If
        Catch err As Exception
            Dim rethrow As Boolean = ExceptionPolicy.HandleException(err, "Log Only Policy")
            If (rethrow) Then
                Throw
            End If
        End Try

ExitHandler:
        Return xelemReturn

    End Function

    '
    '
    '
    Public Function createSectionFieldData() As XElement
        Dim xelemReturn As XElement = New XElement("Section")
        xelemReturn.SetAttributeValue("N", "Field")
        Return xelemReturn
    End Function

    '
    '
    '
    Public Function createRowFieldData _
    (ByVal strRowIndex As String, _
     Optional ByVal blnAddEmpty As Boolean = False, _
     Optional ByVal stcValue As stcCell = Nothing, _
     Optional ByVal stcEditMode As stcCell = Nothing, _
     Optional ByVal stcFormat As stcCell = Nothing, _
     Optional ByVal stcType As stcCell = Nothing, _
     Optional ByVal stcUICat As stcCell = Nothing, _
     Optional ByVal stcUICod As stcCell = Nothing, _
     Optional ByVal stcUIFmt As stcCell = Nothing, _
     Optional ByVal stcCalendar As stcCell = Nothing, _
     Optional ByVal stcObjectKind As stcCell = Nothing) _
    As XElement


        If dictFieldDataFields Is Nothing _
            Or dictFieldDataFields.Count = 0 Then
            dictFieldDataFields = Nothing
            initDictFieldDataFields()
        End If

        Dim intRowIndex As Integer = CInt(strRowIndex)
        Dim xelemReturn As XElement = New XElement("Row")
        Dim cellNew As stcCell = Nothing

        Try

            xelemReturn.SetAttributeValue("IX", strRowIndex)
            For Each fldName In dictFieldDataFields
                Select Case LCase(fldName.Key)
                    Case "value"
                        If stcValue = Nothing Then
                            If blnAddEmpty = True Then
                                xelemReturn.Add(XElement.Load((XmlReader.Create(New StringReader(fldName.Value)))))
                            End If
                        Else
                            xelemReturn.Add(stcValue.writeXelement)
                        End If
                        Exit Select
                    Case "editmode"
                        If stcEditMode = Nothing Then
                            If blnAddEmpty = True Then
                                xelemReturn.Add(XElement.Load((XmlReader.Create(New StringReader(fldName.Value)))))
                            End If
                        Else
                            xelemReturn.Add(stcEditMode.writeXelement)
                        End If
                        Exit Select
                    Case "format"
                        If stcFormat = Nothing Then
                            If blnAddEmpty = True Then
                                xelemReturn.Add(XElement.Load((XmlReader.Create(New StringReader(fldName.Value)))))
                            End If
                        Else
                            xelemReturn.Add(stcFormat.writeXelement)
                        End If
                        Exit Select
                    Case "type"
                        If stcType = Nothing Then
                            If blnAddEmpty = True Then
                                xelemReturn.Add(XElement.Load((XmlReader.Create(New StringReader(fldName.Value)))))
                            End If
                        Else
                            xelemReturn.Add(stcType.writeXelement)
                        End If
                        Exit Select
                    Case "uicat"
                        If stcUICat = Nothing Then
                            If blnAddEmpty = True Then
                                xelemReturn.Add(XElement.Load((XmlReader.Create(New StringReader(fldName.Value)))))
                            End If
                        Else
                            xelemReturn.Add(stcUICat.writeXelement)
                        End If
                        Exit Select
                    Case "uicod"
                        If stcUICod = Nothing Then
                            If blnAddEmpty = True Then
                                xelemReturn.Add(XElement.Load((XmlReader.Create(New StringReader(fldName.Value)))))
                            End If
                        Else
                            xelemReturn.Add(stcUICod.writeXelement)
                        End If
                        Exit Select
                    Case "uifmt"
                        If stcUIFmt = Nothing Then
                            If blnAddEmpty = True Then
                                xelemReturn.Add(XElement.Load((XmlReader.Create(New StringReader(fldName.Value)))))
                            End If
                        Else
                            xelemReturn.Add(stcUIFmt.writeXelement)
                        End If
                        Exit Select
                    Case "calendar"
                        If stcCalendar = Nothing Then
                            If blnAddEmpty = True Then
                                xelemReturn.Add(XElement.Load((XmlReader.Create(New StringReader(fldName.Value)))))
                            End If
                        Else
                            xelemReturn.Add(stcCalendar.writeXelement)
                        End If
                        Exit Select
                    Case "objectkind"
                        If stcObjectKind = Nothing Then
                            If blnAddEmpty = True Then
                                xelemReturn.Add(XElement.Load((XmlReader.Create(New StringReader(fldName.Value)))))
                            End If
                        Else
                            xelemReturn.Add(stcObjectKind.writeXelement)
                        End If
                        Exit Select
                End Select
            Next fldName



        Catch errXml As XmlException
            Dim rethrow As Boolean = ExceptionPolicy.HandleException(errXml, "Log Only Policy")
            If (rethrow) Then
                Throw
            End If
        Catch err As Exception
            Dim rethrow As Boolean = ExceptionPolicy.HandleException(err, "Log Only Policy")
            If (rethrow) Then
                Throw
            End If
        End Try

        Return xelemReturn

    End Function



#End Region

#Region " Section - Tabs "


    '<Section N="Tabs">
    '- <Row IX="0">
    '  <Cell N="Position0" V="0.5" /> 
    '  <Cell N="Alignment0" V="0" /> 
    '  <Cell N="Position1" V="1" /> 
    '  <Cell N="Alignment1" V="0" /> 
    '  <Cell N="Position2" V="1.5" /> 
    '  <Cell N="Alignment2" V="0" /> 
    '  </Row>
    '  </Section>

    '
    ' just for completeness
    '
    Public Function createSectionTabs() As XElement

        Dim xelemReturn As XElement = New XElement("Section")
        xelemReturn.SetAttributeValue("N", "Tabs")

        Dim strDefaultTab As String = "<Section N=""Tabs""> <Row IX=""0""/> </Section>"

        Return XElement.Load((XmlReader.Create(New StringReader(strDefaultTab))))

    End Function


#End Region


    '
    '
    '
    Public Sub New()

    End Sub

    '
    '
    '
    Public Sub New(ByVal newShape As XElement)

        Me._lngShpId = -1
        Me._ShpSource = newShape
        Me._strShpName = "NoShpName"
        Me._strShpName = "NoShpNameU"
        Me._strShpType = "NoShpType"
        Me._lngShpMaster = -1

        Me._xDoc = Nothing
        Me._xDoc = New XDocument

        ' working cell 
        If Me.m_Cell Is Nothing Then
            Me.m_Cell = New clsCell
        End If

        ' sections dictionary
        If Me._dictSections Is Nothing Then
            Me._dictSections = New Dictionary(Of String, XElement)
        End If

        ' cells dictionary
        If Me._dictCells Is Nothing Then
            Me._dictCells = New Dictionary(Of String, XElement)
        End If

        Me._dictRowAttCells = Nothing
        Me._dictRowAttCells = New Dictionary(Of String, String)
        Me._dictRowElemCells = Nothing
        Me._dictRowElemCells = New Dictionary(Of String, String)

        ' initialize the cells and sections dictionaries
        getShapeElements()

    End Sub

    '
    '
    '
    Protected Overrides Sub Finalize()

        If Me.m_Cell IsNot Nothing Then
            Me.m_Cell = Nothing
        End If

        If Me._dictSections IsNot Nothing Then
            Me._dictSections = Nothing
        End If

        If Me._dictCells IsNot Nothing Then
            Me._dictCells = Nothing
        End If

        Me.ShpSource = Nothing
        Me.strShpName = ""
        Me.strShpNameU = ""
        Me.strShpType = ""
        Me.lngShpMaster = -1

        MyBase.Finalize()
    End Sub


    '
    '
    '
    Partial Public Class Point

        Public Property X() As Long
        Public Property Y() As Long

        Public Sub New(ByVal xPos As Long, ByVal yPos As Long)
            X = xPos
            Y = yPos
        End Sub

        Public Overrides Function ToString() As String
            Return String.Format("[{0}, {1}]", Me.X, Me.Y)
        End Function

        Public Shared Operator +(ByVal p1 As Point, ByVal p2 As Point)
            Return New Point(p1.X + p2.X, p1.Y + p2.Y)
        End Operator

        Public Shared Operator -(ByVal p1 As Point, ByVal p2 As Point)
            Return New Point(p1.X - p2.X, p1.Y - p2.Y)
        End Operator

    End Class

End Class
